! 제품 버전을 정확하게 입력해 주세요.
제품 버전이 정확하게 기재되어 있지 않은 경우,
최신 버전을 기준으로 안내 드리므로
더욱 빠르고 명확한 안내를 위해
제품 버전을 정확하게 입력해 주세요!

JavaScript에서 CollectionView로 데이터 시각화하는 방법 > 블로그 & Tips

본문 바로가기

JavaScript에서 CollectionView로 데이터 시각화하는 방법

페이지 정보

작성자 GrapeCity 작성일 2019-05-13 16:55 조회 3,179회 댓글 0건

본문

데이터 시각화는 중요한 주제입니다. JavaScript 애플리케이션에 차트, 그래프, 게이지 및 맵을 추가하는 데 사용할 수 있는 도구에 대해 설명하는 훌륭한 기사가 많이 있습니다.


이 포스팅에서는 그동안 잘 다루지 않은 주제(차트, 그래프, 게이지 및 맵 작성을 위한 데이터 준비)를 다뤄 보겠습니다.


예를 들어, 제품 별 판매량을 보여주는 차트를 작성한다고 가정해보겠습니다. 데이터는 서버에서 다음 형식으로 제공됩니다.


이미지 1


다음은 데이터에 대한 좋은 아이디어를 제공하기 위해 수천 개의 데이터 항목이 포함된 샘플입니다. https://react-ts-epqaqu.stackblitz.io/#raw


첫번째 방법은 서버에서 직접 요약된 버전의 데이터를 가져 오는 방법이 있습니다. 아마도 IT 부서는 이미 필요한 형식으로 데이터를 반환하는 쿼리를 이미 생성했을 것입니다. 운이 좋으면 국가, 제품, 직원 및 지불 방법 별로 데이터를 요약한 쿼리가 있을 수 있지만, 불행하게도 IT 부서의 많은 사람들은 너무 바빠서 관리하는 데이터베이스에 이미 수천 개의 테이블과 쿼리가 있을 것이며, 그것을 바꾸거나 추가하는 작업은 시간이 많이 걸리는 프로세스일 수 있습니다.


또 다른 방법은 몇줄의 JavaScript 코드를 사용하여 클라이언트의 데이터를 요약하는 것입니다. 데이터를 스캔하고 그룹을 작성하며 하나 이상의 속성을 누적하는 메소드를 작성합니다. 그룹화하기 전에 데이터를 필터링하고 정렬하는 다른 방법을 작성하여 특정 제품이나 국가의 판매량을 표시할 수도 있습니다.


CollectionView를 사용하여 데이터 그룹화


Wijmo의 CollectionView 클래스는 이미 모든 것을 수행할 수 있습니다. FlexGrid 및 FlexChart 포함한 모든 Wijmo 컨트롤에 대한 정렬, 필터링 및 그룹화를 제공합니다 .


아래 이미지에서 동일한 데이터를 볼 수 있으며, CollectionView로 정렬 및 그룹화되어 FlexGrid에 표시되어 있습니다.


이미지 2


왼쪽의 그리드는 축소 가능한 그룹으로 구성된 데이터를 보여줍니다. 오른쪽의 그리드는 데이터 항목이 없는 그룹만 표시합니다.


이 그리드를 만드는 데 사용한 코드는 다음과 같습니다.

https://stackblitz.com/edit/react-ts-epqaqu?file=components%2FGroupedData.tsx
export class GroupedData extends Component<CardProps, CardState> {
  constructor(props) {
    super(props);
    const view = new CollectionView(this.props.data, {
      sortDescriptions: ['product', 'country'],
      groupDescriptions: ['product', 'country'],
      collectionChanged: s => {
        if (this.state) {
          this.setState({ groups: s.groups });
        }
      }
    });

    this.state = {
      view: view,
      groups: view.groups
    }
  }


이 코드는 Product 및 Country 별로 정렬되고 그룹화된 CollectionView 만듭니다. 그것은 CollectionView CollectionView의 그룹 컴포넌트 상태에 추가합니다.


컴포넌트의 render 메소드는 FlexGrid 컨트롤의 두 컬렉션을 보여줍니다.

render() {
  return (
    <div id={this.props.id} className="card">
      <h2>
        Grouping Data with CollectionView
      </h2>
      <p>…</p>
      <div className="row">
        <div className="col-xs-6">
          <p className="caption">Grouped Data</p>
          <FlexGrid
            alternatingRowStep={0}
            itemsSource={this.state.view} />
        </div>
        <div className="col-xs-6">
          <p className="caption">Groups</p>
          <FlexGrid
            childItemsPath="groups"
            autoGenerateColumns={false}
            columns={[
              { binding: 'name', header: 'Name', width: '2*' },
              { binding: 'items.length', header: 'Items', width: '*' }
            ]}
            itemsSource={this.state.groups} />
        </div>
      </div>
    </div>
  );
}


이것은 올바른 방향으로 가는 단계이지만, 데이터는 여전히 차트 작성 준비가 되어 있지 않습니다. 그룹 컬렉션의 항목에 집계(aggregate)를 추가해야 합니다.


ChartView를 사용하여 롤업 및 피벗 만들기


동일한 코드를 반복해서 다시 쓰지 않기 위해 CollectionView 를 확장하고 두 가지 메소드를 추가하는 ChartView 클래스를 작성하겠습니다.


  • getRollup : 각 그룹에 해당하는 항목과 선택한 필드에 추가된 집계가 포함된 배열을 반환하는 메서드입니다. getRollup 메서드는 SQL ROLLUP 명령과 같습니다.
  • getPivot : 그룹을 행이 아닌 열로 변환하여 배열로 반환하는 메서드입니다. getPivot메서드는 SQL PIVOT 명령과 같습니다.

이 포스팅에서는 ChartView 코드의 세부 사항에 대해 논의하지는 않지만 관심이 있다면 여기에서 소스 코드를 확인해 보세요.

https://stackblitz.com/edit/react-ts-epqaqu?file=ChartView% 2FChartView.ts


ChartView를 사용한 롤업 차트


롤업(요약) 차트를 만들기 위해 ChartView를 사용하는 것은 쉽습니다. 방법은 다음과 같습니다.


  1. 평소와 같이 뷰를 작성하여 사용하려는 로우 데이터, 정렬 및 그룹 설명을 전달합니다.
  2. 뷰의 getRollup 메서드를 호출하여 요약된 데이터가 있는 배열을 가져옵니다.
  3. 롤업 배열을 FlexChart 컨트롤의 itemsSource로 사용합니다.


https://react-ts-epqaqu.stackblitz.io/#rollup에서 예제를 볼 수 있습니다.


차트는 다음과 같습니다.


이미지 3


첫 번째 차트는 제품별 판매와 비용을, 두 번째 차트는 국가별로 어떻게 요약되어 있는지 확인해보세요. 두 차트 모두 라이브 차트입니다. 로우 데이터를 편집하면 자동으로 업데이트됩니다. 차트 옆의 그리드를 정렬하면 정렬된 데이터를 표시하도록 업데이트됩니다.


차트를 만드는 데 사용되는 코드는 아래와 같이 매우 간단합니다.

https://stackblitz.com/edit/react-ts-epqaqu?file=components%2FSummaryChart.tsx
export class SummaryChart extends Component<CardProps, CardState> {
  constructor(props) {
    super(props);

    let rollupByProduct = new ChartView(this.props.data, {
      sortDescriptions: ['product'],
      groupDescriptions: ['product']
    }).getRollup();
    let rollupByCountry = new ChartView(this.props.data, {
      sortDescriptions: ['country'],
      groupDescriptions: ['country']
    }).getRollup();

    this.state = {
      rollupByProduct: new CollectionView(rollupByProduct),
      rollupByCountry: new CollectionView(rollupByCountry)
    }
  }


이 코드는 두 개의 롤업 배열을 만들어 컴포넌트 상태에 rollupByProduct 및 rollupByCountry  추가합니다이 예제에서는 추가 CollectionView 객체들을 모두 래핑하여 그리드에서 정렬하면 차트가 자동으로 업데이트됩니다.


데이터가 준비되면 차트를 쉽게 만들 수 있습니다. render 메서드는 FlexChart 컨트롤에 대한 데이터 소스로 롤업을 사용합니다 :

render() {
  return (
    <div id={this.props.id} className="card">
      <h2>
        Creating Charts with ChartView.getRollup
      </h2>
      <div className="row">
        <div className="col-xs-6">
          <FlexChart
            bindingX="product"
            series={[
              { binding: 'sales', name: 'Sales' },
              { binding: 'expenses', name: 'Expenses' }
            ]}
            itemsSource={this.state.rollupByProduct}/>
        </div>
      </div>
      <div className="row">
        <div className="col-xs-6">
          <FlexChart
            bindingX="country"
            series={[
              { binding: 'sales', name: 'Sales' },
              { binding: 'expenses', name: 'Expenses' }
            ]}
            itemsSource={this.state.rollupByCountry}/>
        </div>
      </div>
    </div>
  );
}


필터링 된 롤업 차트


ChartView 클래스가 CollectionView를 확장하기 때문에, 생성된 롤업과 피벗은 필터 메서드를 사용하여 필터링 될 수 있습니다.


https://react-ts-epqaqu.stackblitz.io/#filter 에서 예제를 확인할 수 있습니다.


이 앱은 판매 및 비용이 포함된 시계 열 차트를 보여 주며, 집중할 제품 및 국가를 선택할 수 있습니다.


이미지 4


소스 코드는 앞에서 본 것과 비슷하며 사용자가 국가 또는 제품을 선택할 때 호출 되는 filter 메소드가 추가되었습니다.

https://stackblitz.com/edit/react-ts-epqaqu?file=components%2FFilteredChart.tsx
export class FilteredChart extends Component<CardProps, CardState> {
  dateFormat = 'MMM yyyy'; //'"Q"q yyyy';

  constructor(props) {
    super(props);
    let view = new ChartView(this.props.data, {
      sortDescriptions: ['date'], // sort by date
      groupDescriptions: [ // group by formatted date
        new PropertyGroupDescription('date', (item: any) => {
          return format('{date:' + this.dateFormat + '}', item);
        })
      ],
      filter: item => { // filter by selected product/country
        let product = this.state ? this.state.product : '';
        if (product && item.product != product) return false;
        let country = this.state ? this.state.country : '';
        if (country && item.country != country) return false;
        return true;
      }
    });
    this.state = {
      country: '',
      product: '',
      rollup: view.getRollup()
    }
  }


이 코드는 제품 및 국가별로 데이터를 필터링하고 월별로 데이터를 그룹화하는 ChartView를 만듭니다월과 연도를 표시하도록 서식화 된 날짜를 리턴하는 함수를 기반으로 GroupDescription 사용하여 이를 수행합니다. 날짜 형식을 변경하여 분기 또는 연도별로 데이터를 쉽게 그룹화할 수 있었습니다.


render 메서드는 차트 뿐만 아니라 필터를 보여주고 업데이트하는 역할을 합니다.

render() {
  return (
    <div id={this.props.id} className="card">
      <h2>
        Data Filtering with ChartView.getRollup
      </h2>
      <p>…</p>
      <p>
        Select country and product to chart:
        <ComboBox
          isRequired={false}
          placeholder="(All Countries)"
          itemsSource={this.props.countries}
          text={this.state.country}
          textChanged={(s) => {
            this.setState({ country: s.text });
            this.state.rollup.view.refresh();
          }} />
        <ComboBox
          isRequired={false}
          placeholder="(All Products)"
          itemsSource={this.props.products}
          text={this.state.product}
          textChanged={(s) => {
            this.setState({ product: s.text });
            this.state.rollup.view.refresh();
          }} />
      </p>


컴포넌트는 ComboBox 컨트롤을 사용하여 현재 제품 및 국가를 표시합니다. 값이 변경되면 상태가 업데이트되고 뷰가 새로 고쳐집니다.


데이터가 준비되면 차트를 만드는 것은 쉽습니다.

      <div className="row">
        <div className="col-xs-6">
          <FlexChart
            chartType={ChartType.Line}
            bindingX="date"
            series={[
              { binding: 'sales', name: 'Sales' },
              { binding: 'expenses', name: 'Expenses' }
            ]}
            itemsSource={this.state.rollup}
          />
        </div>
        <div className="col-xs-6">
          <FlexGrid…/>
        </div>
      </div>
    </div>
  );
}


드릴 다운 차트


getRollup 메서드는 모든 그룹 레벨의 요약을 생성할 수 있으며, 그 요약은 드릴다운 차트를 만들 수 있습니다.


드릴 다운 차트를 사용하면 국가와 같은 차트 요소를 더블 클릭하여 드릴다운할 수 있으며, 해당 요소의 세부 정보 (예를 들면, 해당 국가의 제품 판매)를 확인할 수 있습니다.


드릴 다운 및 백업을 지원하는 이벤트 핸들러를 추가하고 차트 계층을 표시하고 차트의 계층 구조를 탐색하는 것은 그리 어렵지 않지만 rollupArray 클래스에는 이러한 세부 사항을 표준 방식으로 처리하는 enableDrillDown 메소드가 있으므로 더욱 간단하게 처리할 수 있습니다.


제품별 판매량을 보여주는 예는 다음과 같습니다. 

https://react-ts-epqaqu.stackblitz.io/#drilldown


제품을 더블 클릭하면 이번에는 국가별로 해당 제품의 판매 및 비용이 차트에 표시됩니다. 지불 방법 및 직원별로 판매 및 비용을 확인하기 위해 드릴 다운을 계속할 수 있습니다.


차트를 탐색 할 때 차트 위의 요소는 보고 있는 내용을 표시하고 한 번에 하나 이상의 레벨을 드릴 백 할 수 있습니다.


이미지 5


대부분의 어려운 작업은 ChartView클래스 (및 해당 RollupArray 도우미)에 의해 수행되므로 드릴 다운 차트를 만드는 데 필요한 코드는 매우 선언적이고 간단합니다.

https://stackblitz.com/edit/react-ts-epqaqu?file=components%2FDrillDownChart.tsx
export class DrillDownChart extends Component<CardProps, CardState> {
  constructor(props) {
    super(props);

    let rollup = new ChartView(this.props.data, {
      sortDescriptions: ['product', 'country', 'payment', 'employee'],
      groupDescriptions: ['product', 'country', 'payment', 'employee']
    }).getRollup();

    this.state = {
      rollup: rollup
    }
  }


생성자는 4개의 그룹화 레벨로 뷰를 작성하고 getRollup 메소드를 사용하여 드릴 다운 차트의 데이터 소스로 사용될 계층적 배열을 얻습니다.


차트 자체를 렌더링하는 것에 더해, render 메소드는 사이트 이동 경로를 표시하는 "브레드크럼브(Breadcrumbs)" 요소를 작성합니다.

render() {
  return (
    <div id={this.props.id} className="card">
      <h2>
        Drill-Down Charts with ChartView.getRollup
      </h2>
      <p>…</p>
      <div className="row">
        <div className="col-xs-6">
          <div id="crumbs" className="crumbs"></div>
          <FlexChart
            bindingX="$rollupInfo.group.name"
            series={[
              { binding: 'sales', name: 'Sales' },
              { binding: 'expenses', name: 'Expenses' }
            ]}
            itemsSource={this.state.rollup}
            initialized={s => { 

                // enable drill-down and crumbs
                let crumbs = document.getElementById('crumbs');
                this.state.rollup.enableDrillDown(s, crumbs);

                // add some animation to the chart
                new ChartAnimation(s, {
                  animationMode: AnimationMode.All,
                  easing: Easing.EaseOutElastic,//.Swing,
                  duration: 800
                });
            }}/>
        </div>
        <div className="col-xs-6">
          <FlexGrid…/>
        </div>
      </div>
    </div>
  );
}


컴포넌트가 차트의 initialize 이벤트를 사용하는 두가지 방법은 다음과 같습니다.


  1. 뷰의 내장 드릴 다운 동작(마우스 및 사이트 이동 경로 탐색)을 활성화하기 위해
  2. 차트에 애니메이션을 추가하여 사용자가 차트를 탐색할 때 차트가 한번에 모두 변경되는 것이 아니라 멋진 전환을 사용하여 변경되게 하기 위해


피벗 차트


롤업은 차트 작성을 위한 강력하고 편리한 방법입니다. 롤업은 로우 데이터를 쉽게 요약하여 국가, 제품 또는 날짜별로 판매량을 표시할 수 있습니다. 또한 한 줄의 코드를 사용하여 사용자가 동일한 차트에서 여러 그룹 수준을 탐색할 수 있는 드릴 다운 차트도 만들 수 있습니다.


그러나 여전히 부족한 부분이 있습니다. 제품별 및 국가별 판매를 동일한 차트에 한 번에 모두 표시하려면 어떻게 해야 할까요?


ChartView의 getPivot 메서드는 그룹이 행이 아닌 열로 표시되는 데이터 요약을 만들 수 있도록 합니다. 


getPivot 메서드는 Wijmo의 OLAP 모듈의 하나로서 전체 피벗 엔진처럼 강력하고 유연하지는 않지만, 매우 간단하고 사용하기 쉬우며, 많은 경우에 차트 작성에 필요한 모든 것이 될 수 있습니다.


예를 들면 다음과 같습니다. https://react-ts-epqaqu.stackblitz.io/#pivot


이미지 6


위 차트는 제품별 판매량을 국가별로 분류하여 보여줍니다. 이 샘플에는 국가별 판매량을 제품별로 분류한 다른 차트가 포함되어 있습니다. 컴포넌트는 다음과 같습니다.

https://stackblitz.com/edit/react-ts-epqaqu?file=components%2FPivotChart.tsx
export class PivotChart extends Component<CardProps, CardState> {
  constructor(props) {
    super(props);

    let pivotPC = new ChartView(this.props.data, {
      sortDescriptions: ['product', 'country'],
      groupDescriptions: ['product', 'country']
    }).getPivot('sales');
    let pivotCP = new ChartView(this.props.data, {
      sortDescriptions: ['country', 'product'],
      groupDescriptions: ['country', 'product']
    }).getPivot('sales');

    this.state = {
      pivotPC: pivotPC,
      stackPC: true,
      pivotCP: pivotCP,
      stackCP: true,
    }
  }


컴포넌트는 제품 및 국가별로 그룹화된 뷰와 국가 및 제품별로 그룹화된 뷰를 만듭니다. getPivot 메소드를 사용하여 평소와 같이 판매 값을 집계하고 그룹화하지만, 이번에는 리턴된 값이 두 번째 그룹 (국가 또는 제품)의 각 값에 대한 추가 열을 포함 하는 pivotArray입니다.


컴포넌트 상태에는 계열을 차트에 쌓을지의 여부를 결정하는 member도 포함됩니다.


render 메서드는 차트를 만들기 위해 이 데이터를 사용합니다. :

render() {
    return (
      <div id={this.props.id} className="card">
        <h2>
          Pivot Charts with ChartView.getPivot
        </h2>
        <p>…</p>
        <div className="row">
          <div className="col-xs-6">
            <p className="caption">
              Sales by Product and Country
              <label>
                Stacked
                <input type="checkbox"
                  defaultChecked={this.state.stackPC}
                  onChange={() => {
                    this.setState({stackPC: !this.state.stackPC });
                  } } />
              </label>
            </p>
            <FlexChart
              bindingX="product"
              stacking={this.state.stackPC ? Stacking.Stacked : Stacking.None}
              series={this.state.pivotPC.chartSeries}
              itemsSource={this.state.pivotPCView} />
          </div>
          <div className="col-xs-6">
            <FlexGrid…/>
          </div>
        </div>


render 메서드는 차트의 stacking 속성을 보여주고 토글하기 위해 입력 요소를 사용합니다.


어떻게 차트의 series 속성이 pivotArray 제공하는 배열로 설정되어 있는지 주목해야 합니다. 이 경우 배열에는 각 국가마다 하나의 계열이 포함됩니다. 국가가 데이터에서 추가되거나 제거되면 차트가 자동으로 업데이트되고 데이터와 일치하도록 계열이 추가되거나 제거됩니다.


두 번째 차트(국가 및 제품 별 판매)를 생성하는 코드는 거의 동일합니다.

  <div className="row">
       <div className="col-xs-6">
          <p className="caption">
            Sales by Country and Product
            <label>
              Stacked
              <input type="checkbox"
                defaultChecked={this.state.stackCP}
                onChange={() => {
                  this.setState({ stackCP: !this.state.stackCP });
                }} />
            </label>
          </p>
          <FlexChart
            bindingX="country"
            stacking={this.state.stackCP ? Stacking.Stacked : Stacking.None}
            series={this.state.pivotCP.chartSeries}
            itemsSource={this.state.pivotCPView} />
        </div>
        <div className="col-xs-6">
          <FlexGrid…/>
        </div>
      </div>
    </div>
  );
}
  • 페이스북으로 공유
  • 트위터로  공유
  • 링크 복사
  • 카카오톡으로 보내기

댓글목록

등록된 댓글이 없습니다.

메시어스 홈페이지를 통해 제품에 대해서 더 자세히 알아 보세요!
홈페이지 바로가기

태그1

인기글

더보기
  • 인기 게시물이 없습니다.
메시어스 홈페이지를 통해 제품에 대해서 더 자세히 알아 보세요!
홈페이지 바로가기
이메일 : sales-kor@mescius.com | 전화 : 1670-0583 | 경기도 과천시 과천대로 7길 33, 디테크타워 B동 1107호 메시어스(주) 대표자 : 허경명 | 사업자등록번호 : 123-84-00981 | 통신판매업신고번호 : 2013-경기안양-00331 ⓒ 2024 MESCIUS inc. All rights reserved.