Skip to content
This repository was archived by the owner on Sep 22, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Next Next commit
Concat along axis 1 for DataFrame
  • Loading branch information
mjclawar committed Aug 10, 2017
commit 94990503aca054a3b947f9b555b9810989c77e54
13 changes: 13 additions & 0 deletions src/es6/__tests__/core/reshape/concat.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,5 +62,18 @@ describe('concat', () => {
expect(frame3.get('x').values.toArray()).toEqual([1, 2, 3, 2, 3, 4]);
expect(frame3.get('x').index.toArray()).toEqual([0, 1, 2, 3, 4, 5]);
});

it('Concatenates two DataFrames along axis = 1 without ignoring index', () => {
const frame1 = new DataFrame([{x: 1, y: 2}, {x: 2, y: 3}, {x: 3, y: 4}]);
const frame2 = new DataFrame([{x: 2, y: 3}, {x: 3, y: 4}, {x: 4, y: 5}]);

const frame3 = concat([frame1, frame2], {axis: 1});
expect(frame3.get('x').values.toArray()).toEqual([1, 2, 3]);
expect(frame3.get('y').values.toArray()).toEqual([2, 3, 4]);
expect(frame3.get('x.x').values.toArray()).toEqual([2, 3, 4]);
expect(frame3.get('x.x').name).toEqual('x.x');
expect(frame3.get('y.x').values.toArray()).toEqual([3, 4, 5]);
expect(frame3.get('y.x').name).toEqual('y.x');
});
});
});
68 changes: 40 additions & 28 deletions src/es6/core/reshape/concat.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ type T_ITER_SERIES = Array<Series> | Immutable.List<Series>;

type T_KWARGS = {
ignore_index: boolean,
axis?: 0 | 1,
}

const _concatSeriesValues = (objs: T_ITER_SERIES) =>
Expand Down Expand Up @@ -64,34 +65,45 @@ const _concatDataFrame = (objs: Array<DataFrame> | Immutable.List<DataFrame>,
return objs.get(0);

let seriesOrderedMap = Immutable.OrderedMap({});
objs.forEach((df: DataFrame) => {
const lenSeriesInMap = seriesOrderedMap.keySeq().size === 0
? 0
: seriesOrderedMap.first().length;
const nextLength = df.length + lenSeriesInMap;

seriesOrderedMap = Immutable.OrderedMap(
// Get entries already concated (already in seriesOrderedMap)
seriesOrderedMap.entrySeq().map(([column, series]) => {
if (df.columnExists(column))
if (kwargs.axis === 1) {
objs.forEach((df: DataFrame) => {
df.columns.forEach((column: string) => {
const columnExists = seriesOrderedMap.has(column);
seriesOrderedMap = seriesOrderedMap.set(
columnExists ? `${column}.x` : column, // $FlowIssue
columnExists ? df.get(column).rename(`${column}.x`) : df.get(column));
});
});
} else {
objs.forEach((df: DataFrame) => {
const lenSeriesInMap = seriesOrderedMap.keySeq().size === 0
? 0
: seriesOrderedMap.first().length;
const nextLength = df.length + lenSeriesInMap;

seriesOrderedMap = Immutable.OrderedMap(
// Get entries already concated (already in seriesOrderedMap)
seriesOrderedMap.entrySeq().map(([column, series]) => {
if (df.columnExists(column))
return [
column, // $FlowIssue
_concatSeries([series, df.get(column)], kwargs)];
return [
column, // $FlowIssue
_concatSeries([series, df.get(column)], kwargs)];
return [
column, // $FlowIssue
_concatSeries([
series,
new Series(Immutable.Repeat(NaN, df.length).toList(), {index: df.index})],
kwargs)]; // Now merge with columns only in the "right" DataFrame
})).merge(Immutable.OrderedMap(
df.columns
.filter(column => !seriesOrderedMap.has(column))
.map(column => // $FlowIssue
([column, lenSeriesInMap === 0 ? df.get(column) : _concatSeries([
new Series(Immutable.Repeat(NaN, nextLength)),
df.get(column)],
kwargs)]))));
});
_concatSeries([
series,
new Series(Immutable.Repeat(NaN, df.length).toList(), {index: df.index})],
kwargs)]; // Now merge with columns only in the "right" DataFrame
})).merge(Immutable.OrderedMap(
df.columns
.filter(column => !seriesOrderedMap.has(column))
.map(column => // $FlowIssue
([column, lenSeriesInMap === 0 ? df.get(column) : _concatSeries([
new Series(Immutable.Repeat(NaN, nextLength)),
df.get(column)],
kwargs)]))));
});
}

return new DataFrame(seriesOrderedMap);
};
Expand All @@ -113,13 +125,13 @@ const _concatDataFrame = (objs: Array<DataFrame> | Immutable.List<DataFrame>,
* // Returns Series([1, 2, 3, 4, 2, 3, 4, 5], {index: [0, 1, 2, 3, 4, 5, 6, 7]})
* concat([series1, series2], {ignore_index: true});
*/
const concat = (objs: T_OBJS, kwargs: T_KWARGS = {ignore_index: false}): T_CONCAT => {
const concat = (objs: T_OBJS, kwargs: T_KWARGS = {ignore_index: false, axis: 0}): T_CONCAT => {
if ((Array.isArray(objs) && objs[0] instanceof Series)
|| (objs instanceof Immutable.List && objs.get(0) instanceof Series))
return _concatSeries(objs, {ignore_index: kwargs.ignore_index});
else if ((Array.isArray(objs) && objs[0] instanceof DataFrame)
|| (objs instanceof Immutable.List && objs.get(0) instanceof DataFrame))
return _concatDataFrame(objs, {ignore_index: kwargs.ignore_index});
return _concatDataFrame(objs, {ignore_index: kwargs.ignore_index, axis: kwargs.axis});
throw new Error('Not supported');
};

Expand Down
2 changes: 1 addition & 1 deletion src/es6/core/series.js
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ export default class Series extends NDFrame {
* // Returns List [1, 2, 3]
* ds.index;
*/
set index(index: Immutable.List|Array<number|string>) {
set index(index: Immutable.List | Array<number | string>) {
this.set_axis(0, parseIndex(index, this.values));
}

Expand Down
13 changes: 13 additions & 0 deletions src/js/__tests__/core/reshape/concat.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

60 changes: 35 additions & 25 deletions src/js/core/reshape/concat.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.