Merge branch 'main' into feature-seed-rng

This commit is contained in:
bjoluc 2022-03-11 19:34:31 +01:00
commit 887c247af2
6 changed files with 6639 additions and 2649 deletions

View File

@ -0,0 +1,5 @@
---
"jspsych": minor
---
Added `filterColumns()` to the DataCollection class. This function lets users select a subset of the columns in the DataCollection. It is the opposite of the `ignore()` method.

View File

@ -364,6 +364,15 @@ The filter method returns a DataCollection object, so methods can be chained ont
var block_1_correct = jsPsych.data.get().filter({block:1, correct:true}).count(); var block_1_correct = jsPsych.data.get().filter({block:1, correct:true}).count();
``` ```
#### .filterColumns()
Selects the set of columns listed in the array. This is the opposite of the `.ignore()` method.
```javascript
// Get only the subject, rt, and condition entries for each trial.
const subset_of_data = jsPsych.data.get().filterColumns(['subject', 'rt', 'condition'])
```
#### .filterCustom() #### .filterCustom()
This method is similar to the `.filter()` method, except that it accepts a function as the filter. The function is passed a single argument, containing the data for a trial. If the function returns `true` the trial is included in the returned DataCollection. This method is similar to the `.filter()` method, except that it accepts a function as the filter. The function is passed a single argument, containing the data for a trial. If the function returns `true` the trial is included in the returned DataCollection.

9206
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -21,14 +21,14 @@
"npm": ">=7.0.0" "npm": ">=7.0.0"
}, },
"devDependencies": { "devDependencies": {
"@changesets/changelog-github": "^0.4.1", "@changesets/changelog-github": "^0.4.3",
"@changesets/cli": "^2.17.0", "@changesets/cli": "^2.21.1",
"husky": "^7.0.1", "husky": "^7.0.4",
"import-sort-style-module": "^6.0.0", "import-sort-style-module": "^6.0.0",
"lint-staged": "^11.1.2", "lint-staged": "^12.3.5",
"prettier": "^2.3.2", "prettier": "^2.5.1",
"prettier-plugin-import-sort": "^0.0.7", "prettier-plugin-import-sort": "^0.0.7",
"turbo": "^1.0.6" "turbo": "^1.1.6"
}, },
"prettier": { "prettier": {
"printWidth": 100 "printWidth": 100

View File

@ -134,6 +134,14 @@ export class DataCollection {
return new DataCollection(this.trials.filter(fn)); return new DataCollection(this.trials.filter(fn));
} }
filterColumns(columns: Array<string>) {
return new DataCollection(
this.trials.map((trial) =>
Object.fromEntries(columns.filter((key) => key in trial).map((key) => [key, trial[key]]))
)
);
}
select(column) { select(column) {
const values = []; const values = [];
for (const trial of this.trials) { for (const trial of this.trials) {

View File

@ -15,14 +15,14 @@ describe("DataCollection", () => {
dataCollection = new DataCollection(data); dataCollection = new DataCollection(data);
}); });
test("#filter", () => { test("filter", () => {
expect(dataCollection.filter({ filter: true }).count()).toBe(2); expect(dataCollection.filter({ filter: true }).count()).toBe(2);
}); });
test("#filter OR", () => { test("filter OR", () => {
expect(dataCollection.filter([{ filter: true }, { rt: 300 }]).count()).toBe(2); expect(dataCollection.filter([{ filter: true }, { rt: 300 }]).count()).toBe(2);
expect(dataCollection.filter([{ filter: true }, { rt: 200 }]).count()).toBe(3); expect(dataCollection.filter([{ filter: true }, { rt: 200 }]).count()).toBe(3);
}); });
test("#filterCustom", () => { test("filterCustom", () => {
expect( expect(
dataCollection dataCollection
.filterCustom((x) => { .filterCustom((x) => {
@ -31,43 +31,59 @@ describe("DataCollection", () => {
.count() .count()
).toBe(2); ).toBe(2);
}); });
test("#ignore", () => {
test("filterColumns", () => {
data = [
{ foo: "bar", rt: 100, filter: true },
{ foo: "bar", rt: 200, filter: false },
];
dataCollection = new DataCollection(data);
const filtered_data = dataCollection.filterColumns(["rt", "foo"]);
expect(filtered_data.values()).toEqual([
{ foo: "bar", rt: 100 },
{ foo: "bar", rt: 200 },
]);
});
test("ignore", () => {
expect(dataCollection.ignore("rt").select("rt").count()).toBe(0); expect(dataCollection.ignore("rt").select("rt").count()).toBe(0);
}); });
test("#select", () => { test("select", () => {
expect(JSON.stringify(dataCollection.select("rt").values)).toBe( expect(JSON.stringify(dataCollection.select("rt").values)).toBe(
JSON.stringify([100, 200, 300, 400, 500]) JSON.stringify([100, 200, 300, 400, 500])
); );
}); });
test("#addToAll", () => { test("addToAll", () => {
expect(dataCollection.readOnly().addToAll({ added: 5 }).select("added").count()).toBe(5); expect(dataCollection.readOnly().addToAll({ added: 5 }).select("added").count()).toBe(5);
}); });
test("#addToLast", () => { test("addToLast", () => {
dataCollection.addToLast({ lastonly: true }); dataCollection.addToLast({ lastonly: true });
expect(dataCollection.values()[4].lastonly).toBe(true); expect(dataCollection.values()[4].lastonly).toBe(true);
}); });
test("#readOnly", () => { test("readOnly", () => {
const d = dataCollection.readOnly().values(); const d = dataCollection.readOnly().values();
d[0].rt = 0; d[0].rt = 0;
expect(dataCollection.values()[0].rt).toBe(100); expect(dataCollection.values()[0].rt).toBe(100);
}); });
test("not #readOnly", () => { test("not readOnly", () => {
const d = dataCollection.values(); const d = dataCollection.values();
d[0].rt = 0; d[0].rt = 0;
expect(dataCollection.values()[0].rt).toBe(0); expect(dataCollection.values()[0].rt).toBe(0);
}); });
test("#count", () => { test("count", () => {
expect(dataCollection.count()).toBe(5); expect(dataCollection.count()).toBe(5);
}); });
test("#push", () => { test("push", () => {
dataCollection.push({ rt: 600, filter: true }); dataCollection.push({ rt: 600, filter: true });
expect(dataCollection.count()).toBe(6); expect(dataCollection.count()).toBe(6);
}); });
test("#values", () => { test("values", () => {
expect(JSON.stringify(dataCollection.values())).toBe(JSON.stringify(data)); expect(JSON.stringify(dataCollection.values())).toBe(JSON.stringify(data));
expect(dataCollection.values()).toBe(data); expect(dataCollection.values()).toBe(data);
}); });
test("#first", () => { test("first", () => {
expect(dataCollection.first(3).count()).toBe(3); expect(dataCollection.first(3).count()).toBe(3);
expect(dataCollection.first(2).values()[1].rt).toBe(200); expect(dataCollection.first(2).values()[1].rt).toBe(200);
expect(dataCollection.first().count()).toBe(1); expect(dataCollection.first().count()).toBe(1);
@ -82,7 +98,7 @@ describe("DataCollection", () => {
const too_many = n + 1; const too_many = n + 1;
expect(dataCollection.first(too_many).count()).toBe(n); expect(dataCollection.first(too_many).count()).toBe(n);
}); });
test("#last", () => { test("last", () => {
expect(dataCollection.last(2).count()).toBe(2); expect(dataCollection.last(2).count()).toBe(2);
expect(dataCollection.last(2).values()[0].rt).toBe(400); expect(dataCollection.last(2).values()[0].rt).toBe(400);
expect(dataCollection.last().count()).toBe(1); expect(dataCollection.last().count()).toBe(1);
@ -97,14 +113,14 @@ describe("DataCollection", () => {
const too_many = n + 1; const too_many = n + 1;
expect(dataCollection.last(too_many).count()).toBe(n); expect(dataCollection.last(too_many).count()).toBe(n);
}); });
test("#join", () => { test("join", () => {
const dc1 = dataCollection.filter({ filter: true }); const dc1 = dataCollection.filter({ filter: true });
const dc2 = dataCollection.filter({ rt: 500 }); const dc2 = dataCollection.filter({ rt: 500 });
const data = dc1.join(dc2); const data = dc1.join(dc2);
expect(data.count()).toBe(3); expect(data.count()).toBe(3);
expect(data.values()[2].rt).toBe(500); expect(data.values()[2].rt).toBe(500);
}); });
test("#unqiueNames", () => { test("unqiueNames", () => {
expect( expect(
new DataCollection([ new DataCollection([
{ rt: 100, filter: true }, { rt: 100, filter: true },