Skip to content

Commit 5d543cf

Browse files
authored
Merge pull request #25 from cmu-delphi/sgratzl/upload_grouped
fix: importing grouped data
2 parents 786a7bc + 93a91e4 commit 5d543cf

File tree

3 files changed

+60
-20
lines changed

3 files changed

+60
-20
lines changed

samples/groupby-test.csv

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
2000-01-01,1,5.0
2+
2000-01-01,2,9.0
3+
2000-01-01,3,13.0
4+
2000-01-01,4,17.0
5+
2000-01-02,1,6.0
6+
2000-01-02,2,10.0
7+
2000-01-02,3,14.0
8+
2000-01-02,4,18.0
9+
2000-01-03,1,7.0
10+
2000-01-03,2,11.0
11+
2000-01-03,3,15.0
12+
2000-01-03,4,19.0
13+
2000-01-04,1,8.0
14+
2000-01-04,2,12.0
15+
2000-01-04,3,16.0
16+
2000-01-04,4,20.0

src/components/Chart.svelte

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,28 @@
407407
const cy = (_yMin + _yMax) / 2;
408408
_yMin = cy - dy / 2;
409409
_yMax = cy + dy / 2;
410+
411+
// patch for straight lines
412+
if (_xMin === _xMax) {
413+
if (_xMin !== 0) {
414+
_xMin *= 0.95;
415+
_xMax *= 1.05;
416+
} else {
417+
_xMin = -0.5;
418+
_xMax = 0.5;
419+
}
420+
}
421+
422+
if (_yMin === _yMax) {
423+
if (_yMin !== 0) {
424+
_yMin *= 0.95;
425+
_yMax *= 1.05;
426+
} else {
427+
_yMin = -0.5;
428+
_yMax = 0.5;
429+
}
430+
}
431+
410432
setViewport(_xMin, _yMin, _xMax, _yMax, shouldAnimate);
411433
}
412434

src/data/importCSV.ts

Lines changed: 22 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ export default function importCSV(file: File, fileContent: string, options: CSVO
4040
const lines: string[] = [];
4141
for (const row of fileContent.split('\n')) {
4242
const trimmed = row.trim();
43-
if (trimmed[0] === '#') {
43+
if (trimmed[0] === '#' || trimmed.length === 0) {
4444
continue;
4545
}
4646
lines.push(trimmed);
@@ -94,18 +94,21 @@ export default function importCSV(file: File, fileContent: string, options: CSVO
9494
return asDataGroup(parseGroup(file.name, 0, activeGroup.rows, options, labels));
9595
}
9696
const root: IDataGroup = { title: file.name, level: 0, datasets: [] };
97+
// shift to have at least under the root
98+
const levelOffset = groups.reduce((acc, g) => Math.min(acc, g.level), Number.POSITIVE_INFINITY) - 1;
99+
97100
let active = root;
98101
for (const group of groups) {
99-
const parsed = parseGroup(group.label, group.level, group.rows, options, labels);
100-
if (group.level > active.level) {
102+
const parsed = parseGroup(group.label, group.level - levelOffset, group.rows, options, labels);
103+
if (parsed.level > active.level) {
101104
// child
102105
active.datasets.push(parsed);
103106
parsed.parent = active;
104107
active = parsed;
105108
continue;
106109
}
107110
// multiple levels up
108-
while (group.level < active.level) {
111+
while (parsed.level < active.level) {
109112
active = active.parent!;
110113
}
111114
// sibling
@@ -120,7 +123,7 @@ function parseGroup(title: string, level: number, rows: string[][], options: CSV
120123
const dates = rows.map((row, i) => parseDate(row, i, options));
121124
const datasets: DataSet[] = [];
122125
labels.forEach((label, i) => {
123-
if (isDateColumn(i, options)) {
126+
if (isDateColumn(i, options) || (options.hasGroup && options.groupColumn === i)) {
124127
return;
125128
}
126129
const data = rows.map((row, j) => {
@@ -132,32 +135,31 @@ function parseGroup(title: string, level: number, rows: string[][], options: CSV
132135
return { title, level, datasets };
133136
}
134137

135-
function splitGroup(rows: string[][], prefix: string, level: number, groupColumn: number) {
138+
function splitGroup(
139+
rows: string[][],
140+
prefix: string,
141+
level: number,
142+
groupColumn: number,
143+
): { label: string; level: number; rows: string[][] }[] {
136144
if (rows.length === 0) {
137145
return [];
138146
}
139-
const r: { label: string; level: number; rows: string[][] }[] = [
140-
{
141-
label: prefix + String(rows[0][groupColumn]),
142-
level,
143-
rows: [],
144-
},
145-
];
146-
let active = r[0];
147+
const groups: Map<string, { label: string; level: number; rows: string[][] }> = new Map();
148+
147149
for (const row of rows) {
148150
const group = prefix + String(row[groupColumn]);
149-
if (group != active.label) {
150-
r.push({
151+
const g = groups.get(group);
152+
if (g) {
153+
g.rows.push(row);
154+
} else {
155+
groups.set(group, {
151156
label: group,
152157
level,
153158
rows: [row],
154159
});
155-
active = r[r.length - 1];
156-
} else {
157-
active.rows.push(row);
158160
}
159161
}
160-
return r;
162+
return Array.from(groups.values());
161163
}
162164

163165
function isDateColumn(column: number, options: CSVOptions) {

0 commit comments

Comments
 (0)