Skip to content

Commit

Permalink
DataFrame: addSeries method added (#13)
Browse files Browse the repository at this point in the history
  • Loading branch information
gyrdym committed May 11, 2020
1 parent 068467e commit a20bf61
Show file tree
Hide file tree
Showing 6 changed files with 83 additions and 1 deletion.
3 changes: 3 additions & 0 deletions CHANGELOG.md
@@ -1,5 +1,8 @@
# Changelog

## 0.1.1
- `DataFrame`: addSeries method added

## 0.1.0
- `DataFrame`, `Series`: Serialization/deserialization supported

Expand Down
9 changes: 9 additions & 0 deletions lib/src/data_frame/data_frame.dart
Expand Up @@ -132,12 +132,21 @@ abstract class DataFrame implements Serializable {
/// [Series] is roughly a column and its header (name)
Iterable<Series> get series;

/// Returns a list of two integers representing the shape of the dataframe:
/// the first integer is a number of rows, the second integer - a number of
/// columns
List<int> get shape;

/// Returns a specific [Series] by a key.
///
/// The [key] may be a series name or a series index (ordinal number of the
/// series)
Series operator [](Object key);

/// Returns a dataframe with a new series added to the end of this dataframe's
/// series collection
DataFrame addSeries(Series series);

/// Returns a dataframe, sampled from series that are obtained from the
/// provided series [indices] or series [names].
///
Expand Down
15 changes: 15 additions & 0 deletions lib/src/data_frame/data_frame_impl.dart
Expand Up @@ -2,6 +2,7 @@ import 'package:json_annotation/json_annotation.dart';
import 'package:ml_dataframe/src/data_frame/data_frame.dart';
import 'package:ml_dataframe/src/data_frame/data_frame_helpers.dart';
import 'package:ml_dataframe/src/data_frame/data_frame_json_keys.dart';
import 'package:ml_dataframe/src/data_frame/errors/wrong_series_shape_exception.dart';
import 'package:ml_dataframe/src/data_frame/series.dart';
import 'package:ml_dataframe/src/numerical_converter/helpers/from_numerical_converter_json.dart';
import 'package:ml_dataframe/src/numerical_converter/helpers/numerical_converter_to_json.dart';
Expand Down Expand Up @@ -64,6 +65,12 @@ class DataFrameImpl with SerializableMixin implements DataFrame {
)
final NumericalConverter toNumberConverter;

@override
List<int> get shape => [
series.first?.data?.length ?? 0,
header.length,
];

final Map<DType, Matrix> _cachedMatrices = {};

@override
Expand Down Expand Up @@ -98,6 +105,14 @@ class DataFrameImpl with SerializableMixin implements DataFrame {
return _sampleFromSeries(names);
}

@override
DataFrame addSeries(Series newSeries) {
if (newSeries.data.length != shape.first) {
throw WrongSeriesShapeException(shape.first, newSeries.data.length);
}
return DataFrame.fromSeries([...series, newSeries]);
}

@override
DataFrame dropSeries({
Iterable<int> seriesIndices = const [],
Expand Down
10 changes: 10 additions & 0 deletions lib/src/data_frame/errors/wrong_series_shape_exception.dart
@@ -0,0 +1,10 @@
class WrongSeriesShapeException implements Exception {
WrongSeriesShapeException(this.expectedLength, this.actualLength);

final int expectedLength;
final int actualLength;

@override
String toString() => 'Wrong series shape, expected series data length '
'${expectedLength}, got ${actualLength}';
}
2 changes: 1 addition & 1 deletion pubspec.yaml
@@ -1,6 +1,6 @@
name: ml_dataframe
description: Dataframe - a way to store and manipulate data
version: 0.1.0
version: 0.1.1
homepage: https://github.com/gyrdym/ml_dataframe

environment:
Expand Down
45 changes: 45 additions & 0 deletions test/data_frame/data_frame_test.dart
Expand Up @@ -4,6 +4,7 @@ import 'dart:io';
import 'package:ml_dataframe/ml_dataframe.dart';
import 'package:ml_dataframe/src/data_frame/data_frame.dart';
import 'package:ml_dataframe/src/data_frame/data_frame_json_keys.dart';
import 'package:ml_dataframe/src/data_frame/errors/wrong_series_shape_exception.dart';
import 'package:ml_dataframe/src/numerical_converter/numerical_converter_json_keys.dart';
import 'package:ml_linalg/matrix.dart';
import 'package:test/test.dart';
Expand Down Expand Up @@ -286,6 +287,50 @@ void main() {
});
});

group('addSeries', () {
final series = Series('some new series', <num>[4000, 6000, 9000]);
final invalidSeries1 = Series('invalid series', <num>[4000, 6000, 9000,
1000]);
final invalidSeries2 = Series('invalid series', <num>[4000, 6000]);

test('should add a new series', () {
final dataFrame = DataFrame(data);
final newDataFrame = dataFrame.addSeries(series);

expect(newDataFrame.series.last, series);
});

test('should create a new dataframe', () {
final dataFrame = DataFrame(data);
final newDataFrame = dataFrame.addSeries(series);

expect(newDataFrame, isNot(same(dataFrame)));
});

test('should change dimension of a new dataframe', () {
final dataFrame = DataFrame(data);
final newDataFrame = dataFrame.addSeries(series);

expect(newDataFrame.shape, [3, 4]);
});

test('should throw an exception if a series of invalid shape is '
'provided, case 1', () {
final dataFrame = DataFrame(data);
final newDataFrame = () => dataFrame.addSeries(invalidSeries1);

expect(newDataFrame, throwsA(isA<WrongSeriesShapeException>()));
});

test('should throw an exception if a series of invalid shape is '
'provided, case 2', () {
final dataFrame = DataFrame(data);
final newDataFrame = () => dataFrame.addSeries(invalidSeries2);

expect(newDataFrame, throwsA(isA<WrongSeriesShapeException>()));
});
});

group('serialization', () {
final json = {
dataFrameHeaderJsonKey: ['first', 'second', 'third'],
Expand Down

0 comments on commit a20bf61

Please sign in to comment.