2017-11-14 29 views
0

일부 JSON 데이터를 열 배열로 배열 배열을 사용하는 C3의 timeseries를 그래프로 표시하는 형식으로 변환하려고합니다. 내 고유 한 x 값 배열이 있지만 내 y 값을 얻을 수있는 좋은 방법을 알아낼 수 없습니다. 일단이 작업을 완료하면 numSold와 함께 y2를 추가해야하지만이 문제를 해결할 수 있다면 그 부분을 파악할 수있을 것이라고 생각합니다.C3에서 timeseries를 그래프로 그리기위한 JSON을 배열로 변환하는 더 나은 방법은 무엇입니까?

[ 
    ["x", "9-2-17", "9-4-17", "10-2-17"], 
    ['item1-cost', 100, 150, 10], 
    ['item3-cost', 200, null, 20], 
    ... 
] 

설정 한 날짜의 수 또는 항목의 설정 수는 없다 :

이것은 내가 데이터에 필요한 최종 형식입니다. 그것은 내가 데이터베이스에서 읽은 것입니다. 품목 번호가 반드시 연속적 일 필요는 없습니다. 데이터가있는 항목의 데이터를 그래프로 나타 내기만하면됩니다. 그러나 모든 날짜 - 항목 조합에 대한 데이터는 없습니다. 그런 일이 발생하면 항목에 해당 날짜의 데이터가 없음을 나타 내기 위해 null을 삽입해야합니다. 품목 번호는 1- 색인입니다.

일반 자바 스크립트 함수 외에도 lo-dash 또는 D3을 사용하여 문제를 해결할 수 있지만 코드 및 비효율적 인 코드를 읽지 않으려 고 노력하고 있습니다. 나는 다른 사람들이 이것에 대한 필요성을 느껴야하고 필터 함수와 같은 일종의 함수가 있어야한다고 생각한다.

내 현재 구현 방식은 내가 원하는 것만 큼 효율적이지 않으며 약간 읽기가 어렵습니다. 항목 번호를 색인으로 사용하고 나중에 응축해야하는 희소 배열을 만들고 있습니다. 여기 psudocode는 다음과 같습니다

For every d object in data 
    For the i index of d.date in uniqueDates 
    If values[d.item] is undefined 
     Fill values[d.item]] with null for uniqueDates.length 
    Set values[d.item][i] to d.cost 
Convert values to dense format for graphing 

는 여기에 내가 가지고 노는있어 바이올린에 대한 링크입니다 : 나는이 문제에 관심과 첫 번째 버전으로 등장했다

https://jsfiddle.net/dbkidd/q3r3moqu/

var data = [ 
    {date: '9-2-17', item: 1, cost: 100}, 
    {date: '9-2-17', item: 3, cost: 200}, 
    {date: '9-4-17', item: 1, cost: 150}, 
    /* '9-4-17' does not have an entry for item 3 so cost should be counted as null */ 
    {date: '10-2-17', item: 1, cost: 10}, 
    {date: '10-2-17', item: 3, cost: 20} 
] 

var uniqueDates = _.uniq(_.flatMap(data, 'date')); 
uniqueDates.unshift('x'); 

var values = []; 
values.push(uniqueDates); 

function getLabel(index) { 
    return 'item' + index + '-' + 'cost'; 
} 

for (var d = 0; d < data.length; d++) { 
    var i = _.indexOf(uniqueDates, data[d].date); 
    if (data[d].item !== undefined) { 
    var item = data[d].item; 
    if (values[item] === undefined) { 
     values[item] = _.fill(Array(uniqueDates.length), null); 
     values[item][0] = getLabel(item); 
    } 
    values[item][i] = data[d].cost; 
    } 
} 

function checkIfUndefined(x) { 
    return (x !== undefined); 
} 

function sparseToDense(data) { 
    return data.filter(checkIfUndefined); 
} 

values = sparseToDense(values); 
+0

참고 전적으로 필요는 없다; 빈 배열로 채울 수 있습니다 : https://stackoverflow.com/questions/47295727/how-to-use-sparse-arrays-with-c3-charts – Dallas

답변

1

. 너와는 조금 다르지만 여기에있다. 날짜를 정렬하거나 항목 이름을 유용하게 바꾸지는 않았지만 추가 할 수 있습니다. 희소으로 변환하는 것을 조밀

var data = [ 
 
\t {date: '9-2-17', item: 1, cost: 100}, 
 
    {date: '9-2-17', item: 3, cost: 200}, 
 
    {date: '9-4-17', item: 1, cost: 150}, 
 
    /* '9-4-17' does not have an entry for item 3 so cost should be counted as null */ 
 
    {date: '10-2-17', item: 1, cost: 10}, 
 
    {date: '10-2-17', item: 3, cost: 20}, 
 
    {date: '10-3-17', item: 2, cost: 2000} 
 
] 
 

 
// utility functions 
 
const product = (...sets) => 
 
    sets.reduce((acc, set) => 
 
    _.flatten(acc.map(x => set.map(y => [ ...x, y ]))), 
 
    [[]]); 
 

 
// the meat and potatoes 
 
const builder = lookup => pairs => pairs.reduce((agg, [item, date]) => { 
 
    const out = _.cloneDeep(agg); 
 
    const value = _.get(lookup, [date, item, 'cost'], null); 
 
    const evalue = _.get(out, date, []); 
 
    evalue.push(value); 
 
    _.set(out, date, evalue); 
 
    return out; 
 
}, {}) 
 

 
// setup data structures for searching 
 
const byDateByItem = _.mapValues(_.groupBy(data, 'date'), x => _.keyBy(x, 'item'));  
 
const items = _.uniq(data.map(x=>x.item)); 
 
const dates = _.uniq(data.map(x=>x.date)); 
 

 
// create all posibilities 
 
const pairs = product(items, dates); 
 
// populate possibilities with values 
 
const hash = builder(byDateByItem)(pairs); 
 
// put keys with values in their respective lists 
 
const p = _.toPairs(hash).map(_.flatten); 
 
// smash data into a matrix type thing 
 
const table = [['x',...items], ...p]; 
 
// flip the table on it's side (╯°□°)╯︵ ┻━┻ 
 
const out = _.zip(...table); 
 
console.log('out', out);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>

+0

이봐, 이거 꽤 멋지다. 나는 많은 데이터에 대해 성능이 어떻게 유지 될지 궁금해. – Dallas

+0

초기 jsperf.com 결과는 원래 구현 속도가 빠르지 만 배열이 거대한 경우 true가 유지 될지 잘 모르겠습니다. – Dallas

+1

빠른 타격을 원하지 않는다면 JS를 사용하지 않을 것보다 더 빨리 타격을 가할 것입니다. 대다수의 시간 동안 코드에 대한 미세 최적화를 수행하기 전에 다른 것들을 변경할 수 있습니다. – ktilcu