Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 55 additions & 0 deletions src/danfojs-base/core/series.ts
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,61 @@ export default class Series extends NDframe implements SeriesInterface {
return this.iloc([`${startIdx}:`])
}

/**
* Shift index by desired number of periods. Shifted data is filled with NaN (or fillValue).
* @param periods Number of periods to shift. Positive shifts down, negative shifts up.
* @param options Optional. An object with a `fillValue` property for filling shifted positions.
* @example
* ```
* const sf = new Series([1, 2, 3, 4, 5]);
* const sf2 = sf.shift(1);
* console.log(sf2.values); // [NaN, 1, 2, 3, 4]
* ```
* @example
* ```
* const sf = new Series([1, 2, 3, 4, 5]);
* const sf2 = sf.shift(-1);
* console.log(sf2.values); // [2, 3, 4, 5, NaN]
* ```
*/
shift(periods: number = 1, options?: { fillValue?: number | string | boolean }): Series {
const fillValue = options?.fillValue !== undefined ? options.fillValue : NaN;
const values = this.values as ArrayType1D;
const len = values.length;
const newValues: ArrayType1D = new Array(len).fill(fillValue);

if (periods === 0) {
return this.copy();
}

if (Math.abs(periods) >= len) {
return new Series(newValues, {
index: [...this.index],
columns: this.columns,
dtypes: this.dtypes,
config: { ...this.config }
});
}

if (periods > 0) {
for (let i = periods; i < len; i++) {
newValues[i] = values[i - periods];
}
} else {
const absPeriods = Math.abs(periods);
for (let i = 0; i < len - absPeriods; i++) {
newValues[i] = values[i + absPeriods];
}
}

return new Series(newValues, {
index: [...this.index],
columns: this.columns,
dtypes: this.dtypes,
config: { ...this.config }
});
}

/**
* Returns specified number of random rows in a Series
* @param num The number of rows to return
Expand Down
36 changes: 35 additions & 1 deletion src/danfojs-node/test/core/series.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1755,4 +1755,38 @@ describe("Series Functions", () => {
});

});
})

describe("shift", function () {
it("Shifts values down by 1 with NaN fill", function () {
const sf = new Series([1, 2, 3, 4, 5]);
const result = sf.shift(1);
assert.deepEqual(result.values[0], NaN);
assert.deepEqual(result.values.slice(1), [1, 2, 3, 4]);
});

it("Shifts values up by -1 with NaN fill", function () {
const sf = new Series([1, 2, 3, 4, 5]);
const result = sf.shift(-1);
assert.deepEqual(result.values.slice(0, 4), [2, 3, 4, 5]);
assert.deepEqual(result.values[4], NaN);
});

it("Returns copy when periods is 0", function () {
const sf = new Series([1, 2, 3]);
const result = sf.shift(0);
assert.deepEqual(result.values, sf.values);
});

it("Uses custom fillValue", function () {
const sf = new Series([1, 2, 3, 4]);
const result = sf.shift(2, { fillValue: 0 });
assert.deepEqual(result.values, [0, 0, 1, 2]);
});

it("Returns all fill values when shift exceeds length", function () {
const sf = new Series([1, 2, 3]);
const result = sf.shift(5);
assert.ok(result.values.every((v: any) => isNaN(v)));
});
});
})