@tidyjs/tidy
Version:
Tidy up your data with JavaScript, inspired by dplyr and the tidyverse
89 lines (86 loc) • 2.87 kB
JavaScript
import { groupBy } from './groupBy.js';
import { tidy } from './tidy.js';
function pivotWider(options) {
const _pivotWider = (items) => {
const {
namesFrom,
valuesFrom,
valuesFill,
valuesFillMap,
namesSep = "_"
} = options;
const namesFromKeys = Array.isArray(namesFrom) ? namesFrom : [namesFrom];
const valuesFromKeys = Array.isArray(valuesFrom) ? valuesFrom : [valuesFrom];
const wider = [];
if (!items.length)
return wider;
const idColumns = Object.keys(items[0]).filter((key) => !namesFromKeys.includes(key) && !valuesFromKeys.includes(key));
const nameValuesMap = {};
for (const item of items) {
for (const nameKey of namesFromKeys) {
if (nameValuesMap[nameKey] == null) {
nameValuesMap[nameKey] = {};
}
nameValuesMap[nameKey][item[nameKey]] = true;
}
}
const nameValuesLists = [];
for (const nameKey in nameValuesMap) {
nameValuesLists.push(Object.keys(nameValuesMap[nameKey]));
}
const baseWideObj = {};
const combos = makeCombinations(namesSep, nameValuesLists);
for (const nameKey of combos) {
if (valuesFromKeys.length === 1) {
baseWideObj[nameKey] = valuesFillMap != null ? valuesFillMap[valuesFromKeys[0]] : valuesFill;
continue;
}
for (const valueKey of valuesFromKeys) {
baseWideObj[`${valueKey}${namesSep}${nameKey}`] = valuesFillMap != null ? valuesFillMap[valueKey] : valuesFill;
}
}
function widenItems(items2) {
if (!items2.length)
return [];
const wide = {...baseWideObj};
for (const idKey of idColumns) {
wide[idKey] = items2[0][idKey];
}
for (const item of items2) {
const nameKey = namesFromKeys.map((key) => item[key]).join(namesSep);
if (valuesFromKeys.length === 1) {
wide[nameKey] = item[valuesFromKeys[0]];
continue;
}
for (const valueKey of valuesFromKeys) {
wide[`${valueKey}${namesSep}${nameKey}`] = item[valueKey];
}
}
return [wide];
}
if (!idColumns.length) {
return widenItems(items);
}
const finish = tidy(items, groupBy(idColumns, [widenItems]));
return finish;
};
return _pivotWider;
}
function makeCombinations(separator = "_", arrays) {
function combine(accum, prefix, remainingArrays) {
if (!remainingArrays.length && prefix != null) {
accum.push(prefix);
return;
}
const array = remainingArrays[0];
const newRemainingArrays = remainingArrays.slice(1);
for (const item of array) {
combine(accum, prefix == null ? item : `${prefix}${separator}${item}`, newRemainingArrays);
}
}
const result = [];
combine(result, null, arrays);
return result;
}
export { pivotWider };
//# sourceMappingURL=pivotWider.js.map