Data Loading

To load data into vue-gg, pass data in a supported format to the :data prop of any Graphic, Data or Section component. This will create a data scope for its child components.

Data types

vue-gg supports 6 different data types: quantitative, categorical, temporal, interval, geometry and nested. vue-gg will decide what data type your data is based on what native JavaScript type it has, and for geometry and nested data, what structure it has.

Data type JS type Level of measurement (Smith Stevens)
quantitative Number Interval, Ratio
categorical String Nominal, Ordinal
temporal Date Interval
interval Array (length 2) -
geometry Object (GeoJSON feature) -
nested Object (of Arrays) -

Data formats

While it is possible to load data in various formats into vue-gg, there are some requirements that all data must adhere to:

  • All columns must have the same length
  • All columns have more than 0 valid values (invalid values being NaN, null etc)
  • One column is only allowed to have one data type
  • Column names are not allowed to have the characters ., / and #
  • Data of the geometry type is only allowed in a column called 'geometry', and a column called 'geometry' must always have only data of the type geometry

Tabular data: column-oriented vs row-oriented

Internally, vue-gg stores data in a column-oriented format. Or, in JavaScript terms, an Object where each key is the column name and each value an array of all values for that column:

{
  columnA: [1, 2, 3, 4],
  columnB: ['a', 'b', 'b', 'a']
}

It is recommended to pass data in this format when possible. Alternatively, data can be passed in a row-oriented format, or an Array of Objects:

[
  { columnA: 1, columnB: 'a' },
  { columnA: 2, columnB: 'b' },
  { columnA: 3, columnB: 'b' },
  { columbA: 4, columnB: 'a' }
]

Data passed in this format will internally be converted and stored as column-oriented data. So when your data is originally in column-oriented format, passing it as column-oriented data will save a little bit of conversion time.

GeoJSON

When passing data in a GeoJSON format, the GeoJSON data will be converted to a column-oriented format. For every feature, the geometry will be stored in a column called geometry, and all properties get their own column.

Data scope

Using data scopes

When you load data into a Graphic, Data or Section component, the component in question will create a so-called data scope for its children. This data scope will be the same for all its children until another data scope is created by one of its children. For example:

<vgg-graphic
  :data="{ a: [1, 2, 3, 4], b: [5, 6, 7, 8] }"
>

  <!--
    Here we are within the <vgg-graphic> component's data scope.
    We have access to the data { a: [1, 2, 3, 4], b: [5, 6, 7, 8] }
  -->

  <vgg-section>
    <!-- Here we are still within the <vgg-graphic> component's data scope. -->
  </vgg-section>

  <vgg-section
    :data="{ c: [11, 12, 13, 14], d: [15, 16, 17, 18] }"
  >

    <!-- Here we ware withing a new data scope: the <vgg-section>'s data scope. -->
    <!-- We have access to the data { c: [11, 12, 13, 14], d: [15, 16, 17, 18] } -->

  </vgg-section>

</vgg-graphic>

Besides loading new data, another way to create a new data scope is using the :transform prop to apply transformations to the data:

<vgg-graphic
  :data="{ a: [1, 2, 3, 4], b: [5, 6, 7, 8] }"
>

  <vgg-data
    :transform="{ filter: row => row.a > 2 }"
  >

    <!-- Here we ware withing a new data scope: the <vgg-data>'s data scope. -->
    <!-- We have access to the data { a: [3, 4], b: [7, 8] } -->

  </vgg-data>

</vgg-graphic>

Referencing domains from another data scope

In some cases, it can be handy to have access to columns from a different scope. To access a different data scope, give the component that creates the scope you are interested in an ID with the dataID prop. The data scope can then be accessed from other data scopes using the dataID of the component, followed by /, and the column name:

<vgg-graphic
  :data="{ a: [1, 2, 3, 4], b: [5, 6, 7, 8] }"
  dataID="parentData"
/>

  <vgg-data
    :transform="{ filter: row => row.a > 2 }"
  >

    <vgg-map v-slot="{ row }">

      <vgg-point
        :x="{ val: row.a, scale: { domain: 'a' } }"
        :y="{ val: row.b, scale: { domain: 'parentData/b' } }"
      />

      <!--
        In the x-direction, the points' scale will use the domain of the filtered data.
        In the y-direction, the points' scale will use the domain to the unfiltered data.
      -->

    </vgg-map>

  </vgg-data>

</vgg-graphic>

Accessing another data scope is possible as long as the scope you want to access was declared before you try to access it. This means that you can never access child data scopes, and only access sibling data scopes if the sibling was declared before the scope in question. For example:

<vgg-data dataID="before" :data="someData" />

<vgg-data :data="someOtherData" />
  <vgg-map v-slot="{ row }">
    <vgg-point :x="{ val: row.a, scale: 'before/a' }" />
  </vgg-map>
</vgg-data>

is allowed, but

<vgg-data :data="someOtherData" />
  <vgg-map v-slot="{ row }">
    <vgg-point :x="{ val: row.a, scale: 'after/a' }" />
  </vgg-map>
</vgg-data>

<vgg-data dataID="after" :data="someData" />

is not.