Skip to content

Commit b2456ce

Browse files
authored
Merge pull request #1 from w2sv/develop
Develop
2 parents aaff7ab + 6871bd0 commit b2456ce

23 files changed

+752
-438
lines changed

.github/workflows/build.yaml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,7 @@ jobs:
1414
run: dart pub get
1515

1616
- name: Run tests
17-
run: |
18-
make test-with-coverage
17+
run: make test
1918

2019
- name: Upload coverage to codecov
2120
run: |

.gitignore

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -74,10 +74,5 @@ example/ios/Flutter/flutter_export_environment.sh
7474
!**/ios/**/default.perspectivev3
7575
!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
7676

77-
# Coverage report
78-
test/.test_coverage.dart
79-
/coverage/
80-
/coverage-html/
81-
82-
# Test output
83-
/test/output/
77+
# Coverage
78+
/coverage/

.pubignore

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
11
/test/
22
Makefile
3-
/coverage/
4-
/coverage-html/
3+
/coverage/

CHANGELOG.md

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,15 @@ Comply with data file format conventions.
88

99
# 0.0.3
1010

11-
Add 'toCsv' method. Improve method documentation. Remove the rather pointless 'structureInfo' method.
11+
Add `toCsv` method. Improve method documentation. Remove the rather pointless `structureInfo` method.
12+
13+
# 0.1.0
14+
15+
- Add `shape` property, `columnIterable`, `withColumns`, `rowsAt`, `rowsWhere`
16+
- Incorporate `Column` class being returned upon accessing a `DataFrame` column, alongside methods for
17+
- transformation: `cumulativeSum`
18+
- accumulation: `mean`, `max`, `min`, `sum`
19+
- counting: `count`, `countElementOccurrencesOf`
20+
- null-ridding: `nullFree`, `nullFreeIterable`
21+
- mask conversion: `equals`, `unequals`, `isIn`, `isNotIn`, `maskFrom`; operators: `<`, `>`, `<=`, `>=`
22+
- Enable conditional rows selection based on columns, e.g. `final filteredDf = df.rowsWhere((df('a') > 7) & df('b').equals(null))`

Makefile

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,31 @@
11
SHELL=/bin/bash
22

3-
test-with-coverage:
4-
dart pub global activate coverage
5-
dart pub global run coverage:test_with_coverage
3+
# $$$$$$$$$ Testing $$$$$$$$$$
64

7-
coverage:
8-
genhtml coverage/lcov.info -o coverage-html
9-
firefox coverage-html/index.html
5+
test-and-show-coverage: run-tests coverage-html
6+
7+
run-tests:
8+
@dart run test --coverage=./coverage --chain-stack-traces
9+
@echo "Converting to lcov.info"
10+
@dart pub global activate coverage > /dev/null
11+
@dart pub global run coverage:format_coverage --packages=.dart_tool/package_config.json --report-on=lib --lcov -o ./coverage/lcov.info -i ./coverage
12+
13+
coverage-html:
14+
genhtml coverage/lcov.info -o coverage/html
15+
open coverage/html/index.html
16+
17+
# $$$$$$$$$ Publishing $$$$$$$$$$
18+
19+
pre-publish:
20+
@dart format lib
21+
@dart analyze
22+
@dart doc
23+
@dart pub publish --dry-run
24+
25+
patch-version:
26+
dart pub global activate pubversion
27+
pubversion patch
28+
29+
publish:
30+
dart pub publish
31+
gh release create

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ final fromCsv = Dataframe.fromCsv(
2020
path: 'path/to/file.csv',
2121
eolToken: '\n',
2222
maxRows: 40,
23-
skipColumns: ['date'],
23+
skipColumns: ['some-irrelevant-column'],
2424
convertDates: true,
2525
datePattern: 'dd-MM-yyyy'
2626
);

lib/koala.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
library koala;
22

33
export 'src/dataframe.dart';
4+
export 'src/column.dart';

lib/src/column.dart

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
import 'package:collection/collection.dart';
2+
3+
import 'utils/list_base.dart';
4+
5+
class Column<E> extends ListBase<E> {
6+
Column(List<E> records) : super(records);
7+
8+
/// Get a casted [Column].
9+
Column<T> cast<T>() => Column(super.cast<T>());
10+
11+
// ************* count *****************
12+
13+
/// Counts occurrences of [element].
14+
int count(E object) => where((element) => element == object).length;
15+
16+
/// Counts column-elements equaling any element contained by [pool].
17+
int countElementOccurrencesOf(Set<E> pool) =>
18+
where((element) => pool.contains(element)).length;
19+
20+
// ************* null freeing *************
21+
22+
/// Returns [Column] without nulls. If [replaceWith] is set to null null-records
23+
/// are removed from the column, whereas they will replaced by its value otherwise.
24+
Column<E> nullFree({E? replaceWith = null}) =>
25+
Column<E>(nullFreeIterable(replaceWith: replaceWith).toList());
26+
27+
/// Iterable-returning counterpart of [nullFree].
28+
/// Consult [nullFree] for further documentation.
29+
Iterable<E> nullFreeIterable({E? replaceWith = null}) => replaceWith == null
30+
? where((element) => element != null)
31+
: map((e) => e ?? replaceWith);
32+
33+
// ****************** transformation ******************
34+
35+
/// Returns List<num> containing the cumulative sum of the column.
36+
/// [treatNullsAsZeros] being set to true will lead to the the result being of
37+
/// the same length as the original column. Otherwise, null records won't be
38+
/// accounted for.
39+
///
40+
/// Note: requires column records type to be a subtype of <num?>
41+
List<num> cumulativeSum({bool treatNullsAsZeros = true}) =>
42+
_nullFreedNums(treatNullsAsZeros: treatNullsAsZeros).fold(
43+
[],
44+
(sums, element) =>
45+
sums..add(sums.isEmpty ? element : sums.last + element));
46+
47+
// **************** accumulation ****************
48+
49+
/// Returns the column's mean. Set [treatNullsAsZeros] for the method
50+
/// to not account for null records.
51+
///
52+
/// Note: requires column records type to be a subtype of <num?>
53+
double mean({bool treatNullsAsZeros = true}) =>
54+
_nullFreedNums(treatNullsAsZeros: treatNullsAsZeros).average;
55+
56+
/// Returns the column's max. Requires column records type to be a subtype of <num?>
57+
num max() => _nullFreedNums().max;
58+
59+
/// Returns the column's min. Requires column records type to be a subtype of <num?>
60+
num min() => _nullFreedNums().min;
61+
62+
/// Returns the column's sum. Requires column records type to be a subtype of <num?>
63+
num sum() => _nullFreedNums().sum;
64+
65+
Iterable<num> _nullFreedNums({bool treatNullsAsZeros = false}) => cast<num?>()
66+
.nullFreeIterable(replaceWith: treatNullsAsZeros ? 0 : null)
67+
.cast<num>();
68+
69+
// ***************** masks *******************
70+
71+
Mask equals(E reference) =>
72+
map((element) => element == reference).toList().cast<bool>();
73+
74+
Mask unequals(E reference) =>
75+
map((element) => element != reference).toList().cast<bool>();
76+
77+
Mask isIn(Set<E> pool) =>
78+
map((element) => pool.contains(element)).toList().cast<bool>();
79+
80+
Mask isNotIn(Set<E> pool) =>
81+
map((element) => !pool.contains(element)).toList().cast<bool>();
82+
83+
/// Get a [Mask] by mapping [test] to the column records.
84+
Mask maskFrom(bool Function(E) test) => map(test).toList().cast<bool>();
85+
86+
// ****************** numerical column masks *********************
87+
88+
/// Requires the column records type to be a subtype of num (i.e. non-null!)
89+
Mask operator <(num reference) =>
90+
cast<num>().map((element) => element < reference).toList().cast<bool>();
91+
92+
/// Requires the column records type to be a subtype of num (i.e. non-null!)
93+
Mask operator >(num reference) =>
94+
cast<num>().map((element) => element > reference).toList().cast<bool>();
95+
96+
/// Requires the column records type to be a subtype of num (i.e. non-null!)
97+
Mask operator <=(num reference) =>
98+
cast<num>().map((element) => element <= reference).toList().cast<bool>();
99+
100+
/// Requires the column records type to be a subtype of num (i.e. non-null!)
101+
Mask operator >=(num reference) =>
102+
cast<num>().map((element) => element >= reference).toList().cast<bool>();
103+
}
104+
105+
typedef Mask = List<bool>;
106+
107+
/// Operators for the conjunction of masks.
108+
extension MaskExtensions on Mask {
109+
Mask operator &(Mask other) =>
110+
IterableZip([this, other]).map((e) => e.first && e.last).toList();
111+
112+
Mask operator |(Mask other) =>
113+
IterableZip([this, other]).map((e) => e.first || e.last).toList();
114+
115+
Mask operator ^(Mask other) =>
116+
IterableZip([this, other]).map((e) => e.first ^ e.last).toList();
117+
}

0 commit comments

Comments
 (0)