--- layout: default title: Prepare and load your own data nav_order: 3 parent: Build your own Data Commons include_scripts: - /assets/js/customdc-doc-tabs.js - /assets/js/syntax_highlighting.js --- {:.no_toc} # Prepare and load your own data This page shows you how to format and load your own custom data into your local instance. This is step 2 of the [recommended workflow](/custom_dc/index.html#workflow). Please also see the sample data and files provided in [custom_dc/sample](https://github.com/datacommonsorg/website/tree/master/custom_dc/sample){: target="_blank"}. * TOC {:toc} ## Overview Custom Data Commons requires that you provide your data in a specific schema, format, and file structure. We strongly recommend that, before proceeding, you familiarize yourself with the basics of the Data Commons data model by reading through [Key concepts](/data_model.html), in particular, _entities_, _statistical variables_, and _observations_. At a high level, you need to provide the following: * If you need to define your own statistical variables (metrics), you need to provide [MCF (Meta Content Framework)](https://en.wikipedia.org/wiki/Meta_Content_Framework){: target="_blank"} files. * All observations data must be in CSV format, using the schema described later. * You must also provide a JSON configuration file, named `config.json`, that specifies how to map and resolve the CSV contents to the Data Commons schema knowledge graph. The contents of the JSON file are described below. If you need to define new entities, please see [Define custom entities](custom_entities.md) for details. {: #dir} ### Files and directory structure You can have as many CSV and MCF files as you like, and they can be in multiple subdirectories (with an additional [configuration option](#subdirs)). There must only be one JSON config file, in the top-level input directory. For example: ``` my_data/ ├── config.json ├── nodes1.mcf ├── datafile1.csv ├── datafile2.csv └── some_more_data/ ├── nodes2.mcf ├── datafile3.csv └── datafile4.csv ``` The top-level directory (e.g. `my_data`) can live anywhere in the file system; you will specify the full path to it when you [configure your input directory](#env). When you set up your files in Google Cloud Storage using the Terraform script, it will automatically create a top-level directory in your bucket called `input`. The following sections walk you through the process of setting up your data. ## Prerequisite steps The following sections describe the high-level conceptual work you need to do before starting to write your data and config files. {: entities} ### Step 0.1: Determine whether you need new entities or entity types Data Commons is optimized to support aggregations of data at geographical levels, such as city, state, country, and so on. If your data is aggregated by place, these are supported as entities out of the box. If, however, you want to aggregate data for entities that are _not_ places, then you may need to define new entities, and possibly even entity types. In addition, even if you aggregate by geographical area, you may want to measure things (known as a "population type" in the graph) that are not already in the graph. In that case, you might want to to define a new entity type, so that you can join with other data sets that measure the same thing. For example, let's say you have a metric that counts the number of beds in hospitals. The existence of the `Bed` entity type allows you to join your data with other sources with a similar metric. #### Entities and entity types Schema.org and the base Data Commons knowledge graph define entity types for just about everything in the world. An _entity type_ is a high-level concept, and is derived directly from a [`Class`](https://datacommons.org/browser/Class){: target="_blank"} type. Non-place entities are of two types: * The thing you are measuring, known as the `populationType` in Data Commons. Often this is a `Person`, which is a commonly used population in Data Commons. But it could be something else entirely, such as hospital beds, consumer commodities, Olympic medals, oceans, etc.. * The level at which you want to aggregate the data. Most commonly in Data Commons this is a place type such as `City`, `Country`, `AdministrativeArea1`, etc. Examples of other entity types are `Hospital`, `PublicSchool`, `Company`, `BusStation`, `Campground`, `Library` etc. It is rare that you would need to create a new entity type, unless you are working in a highly specialized domain. An _entity_ is an instance of an entity type. For example, for `PublicSchool`, base Data Commons has many U.S. schools in its knowledge graph, such as [`nces/010162001665`](https://datacommons.org/browser/nces/010162001665){: target="_blank"} (Adams Elementary School) or [`nces/010039000201`](https://datacommons.org/browser/nces/010039000201){: target="_blank"} (Wylam Elementary School). Base Data Commons contains thousands of places and other entities, but it's possible that it does not have specific entities that you need. For example, it has about 100 instances of `Company`, but you may want data for other companies besides those. As another example, let's say your organization wants to collect (possibly private) data about different divisions or departments of your org; in this case you would need to define entities for them. > **Note:** You should always reuse existing entity types and entities from base Data Commons rather than re-defining them. This way, you get all the properties already defined for those entities and all their linked nodes, and can more easily join with base data if needed. {: #search} #### Search for an existing entity / entity type It is currently not possible to get a full list of entity types or entities in the Data Commons UI. To do a complete search for an entity type or entity, you need to use the REST or Python APIs. To search using the REST APIs: 1. Use the Node API through your browser to get a complete list of entity types: see [Get a list of all existing entity types](/api/rest/v2/node.html#list-entity-types) in the REST API V2 reference. Be sure to set the `nextToken` parameter until you find the relevant entity type or no `nextToken` is returned in the response. If you don't find an entity type that matches your needs (very rare), you will need to [create one](custom_entities.md). 1. If you find a relevant entity type, note the DCID of the entity type of interest. The DCID of entity types is usually a meaningful name, capitalized, such as `Hospital` or `PowerPlant` or `PublicSchool`. 1. Use the Node API through your browser to look up all incoming arcs by the `typeof` property:
https://api.datacommons.org/v2/node?key=AIzaSyCTI4Xz-UW_G2Q2RfknhcfdAnTHq5X5XuI&nodes=ENTITY_TYPE&property=<-typeOf_ENTITY_TYPE_ is the DCID you've obtained in the previous step, such as `Hospital` or `PublicSchool`. For example: ``` https://api.datacommons.org/v2/node?key=AIzaSyCTI4Xz-UW_G2Q2RfknhcfdAnTHq5X5XuI&nodes=PublicSchool&property=<-typeOf ``` 1. If your entity is listed, note its DCID. If you are unable to find a relevant entity, you will need to create one. See [Work with custom entities](custom_entities.md) for complete information. To search using the Python APIs: 1. Start your Python interactive environment and [create a client for the base Data Commons](/api/python/v2/index.html). 1. Call the `Node` method `fetch_all_classes`: see [Get node properties](https://docs.datacommons.org/api/python/v2/node.html#fetch_all_classes) for details. (Tip: Use the `to_dict()` method on the response to get readable output.) If you don't find an entity type that matches your needs (very rare), you will need to [create one](custom_entities.md). 1. If you find a relevant entity type, note the DCID of the entity type of interest. The DCID of entity types is usually a meaningful name, capitalized, such as `Hospital` or `PowerPlant` or `PublicSchool`. 1. Use the `fetch_property_values` method to find all the instances of the type:
client.node.fetch_property_values(node_dcids="ENTITY_TYPE", properties="typeOf", out=False)_ENTITY_TYPE_ is the DCID you've obtained in the previous step. For example: ``` client.node.fetch_property_values(node_dcids="PublicSchool", properties="typeOf", out=False) ``` 1. If your entity is listed, note its DCID. If you are unable to find a relevant entity, you will need to create one. See [Work with custom entities](custom_entities.md) for complete information. ### Step 0.2: Identify your statistical variables Your data undoubtedly contains metrics and observed values. In Data Commons, the metrics themselves are known as statistical variables, and the time series data, or values over time, are known as observations. While observations are always numeric, statistical variables must be defined as _nodes_ in the Data Commons knowledge graph. Data Commons already has thousands of statistical variables in its knowledge graph; you may be able to simply reuse or extend existing ones. Before creating a new variable, take a look at the [Statistical Variable Explorer](https://datacommons.org/tools/statvar){: target="_blank"} to check if you can use an existing variable to represent the data you are importing. This is important if you want to correctly link your data to data in base Data Commons. In addition, if you ever plan to contribute your data to datacommons.org, it's very important to reuse variables as much as possible, to avoid creating unnecessary duplication that can lead to misleading query results. If you do need to define new variables, they must follow a certain model. The variable consists of a measure (e.g. "median age") on a set of things of a certain type (e.g. "persons") that satisfy some set of constraints (e.g. "gender is female"). To explain what this means, consider the following example. Let's say your dataset contains the number of schools in U.S. cities, broken down by level (elementary, middle, secondary) and type (private, public), reported for each year (numbers are not real, but are just made up for the sake of example): | CITY | YEAR | SCHOOL_TYPE | SCHOOL_LEVEL | COUNT | |------|------|----------------|-------| | San Francisco | 2023 | public | elementary | 300 | | San Francisco | 2023 | public | middle | 300 | | San Francisco | 2023 | public | secondary | 200 | | San Francisco | 2023 | private | elementary | 100 | | San Francisco | 2023 | private | middle | 100 | | San Francisco | 2023 | private | secondary | 50 | | San Jose | 2023 | public | elementary | 400 | | San Jose | 2023 | public | middle | 400 | | San Jose | 2023 | public | secondary | 300 | | San Jose | 2023 | private | elementary | 200 | | San Jose | 2023 | private | middle | 200 | | San Jose | 2023 | private | secondary | 100 | The measure here is a simple count; the set of things is "schools"; and the constraints are the type and levels of the schools, namely "public", "private", "elementary", "middle" and "secondary". All of these things must be encoded as separate variables. Therefore, although the _properties_ of school type and school level may already be defined in the Data Commons knowledge graph (or you may need to define them), they _cannot_ be present as columns in the CSV files that you store in Data Commons. Instead, you must create separate "count" variables to represent each case. In our example, you would actually need 6 different variables: * `Count_School_Public_Elementary` * `Count_School_Public_Middle` * `Count_School_Public_Secondary` * `Count_School_Private_Elementary` * `Count_School_Private_Middle` * `Count_School_Private_Secondary` If you wanted totals or subtotals of combinations, you would need to create additional variables for these as well. If you plan to contribute your data to base Data Commons, you'll also need to ensure that they conform to [naming conventions](#naming-conventions). #### Variable schema Data Commons uses a schema that is called "variable-per-row". This means that every distinct entity-variable pair must appear in a different row. Here's an example: **Variable-per-row schema** | CITY | YEAR | VARIABLE | OBSERVATION | |------|------|-----------|-------| | geoId/0667000 | 2023 | Count_School_Public_Elementary | 300 | | geoId/0667000 | 2023 | Count_School_Public_Middle | 300 | | geoId/0667000 | 2023 | Count_School_Public_Secondary | 200 | | geoId/0667000 | 2023 | Count_School_Private_Elementary | 100 | | geoId/0667000 | 2023 | Count_School_Private_Middle | 100 | | geoId/0667000 | 2023 | Count_School_Private_Secondary | 50 | | geoId/06085 | 2023 | Count_School_Public_Elementary | 400 | | geoId/06085 | 2023 | Count_School_Public_Middle | 400 | | geoId/06085 | 2023 | Count_School_Public_Secondary | 300 | | geoId/06085 | 2023 | Count_School_Private_Elementary | 200 | | geoId/06085 | 2023 | Count_School_Private_Middle | 200 | | geoId/06085 | 2023 | Count_School_Private_Secondary | 100 | The names and order of the columns aren't important, as you can map them to the expected columns in the JSON file. However, the city and variable names must be existing DCIDs. If such DCIDs don't already exist in the base Data Commons, you must provide definitions of them in MCF files. > **Tip:** If your raw data does not conform to this structure (which is typically the case if you have relational data), you can usually easily convert the data by creating a pivot table (and renaming some columns) in a tool like Google Sheets or Microsoft Excel. ## Prepare your data In this section, we will walk you through a concrete example of how to go about setting up your MCF, CSV, and JSON files. {: #mcf} ### Step 1: Define statistical variables in MCF If you are only reusing existing variables, you can skip this step entirely. Nodes in the Data Commons knowledge graph are defined in Metadata Content Format (MCF) files. If you need to define new statistical variables, you must define them as new _nodes_ using MCF. When you define any variable in MCF, you explicitly assign it a DCID. > **Note:** You cannot "override" a variable definition by changing the value of existing fields. If you need to override the values of existing fields, you should create a new variable, with a new DCID. You can define your statistical variables in a single MCF file, or split them into as many separate MCF files as you like. MCF files must have a `.mcf` suffix. The importer will automatically find them when you start the Docker data container. Let's look at an example from a WHO dataset that reports the [prevalence of smoking among adolescents](https://platform.who.int/data/maternal-newborn-child-adolescent-ageing/indicator-explorer-new/MCA/prevalence-of-current-cigarette-smoking-among-adolescents){: target="_blank"} (adolescents are age 13 - 17). | Indicator | Year | Country code | Country | Sex | Value | |-----------|------|--------------|---------|-----|-------| | Prevalence of current cigarette smoking among adolescents | 2018 | ARG | Argentina | Male | 15.5 | | Prevalence of current cigarette smoking among adolescents | 2018 | ARG | Argentina | Female | 20 | | Prevalence of current cigarette smoking among adolescents | 2018 | ARG | Argentina | Both sexes | 18 | | Prevalence of current cigarette smoking among adolescents | 2022 | ARM | Armenia | Male | 17 | | Prevalence of current cigarette smoking among adolescents | 2022 | ARM | Armenia | Female | 0 | | Prevalence of current cigarette smoking among adolescents | 2024 | AUT | Austria | Male | 17.2 | | Prevalence of current cigarette smoking among adolescents | 2024 | AUT | Austria | Female | 21.3 | | Prevalence of current cigarette smoking among adolescents | 2024 | AUT | Austria | Both sexes | 19.5 | The first thing to notice is that there is a breakdown by sex. Therefore, we'll need 3 different variables to represent that dimension: 1 variable for males, 1 variable for females, and 1 variable for both. The second thing is figure out if there are existing entities or properties we can use to represent cigarette smoking, adolescents, and sex. It turns out that there are! * Adolescence is represented by [`Adolescents`](https://datacommons.org/browser/Adolescents){: target="_blank"}, which is a member of the [`AgeGroupClassificationEnum`](https://datacommons.org/browser/AgeGroupClassificationEnum){: target="_blank"}. * Sex is represented by an existing property, [gender](https://datacommons.org/browser/gender){: target="_blank"}, which is of type [`GenderType`](https://datacommons.org/browser/GenderType){: target="_blank"}, an enumeration. Its members [Female](https://datacommons.org/browser/Female){: target="_blank"} and [Male](https://datacommons.org/browser/Male){: target="_blank"} already exist as well. * [Smoking](https://datacommons.org/browser/Smoking){: target="_blank"}, which is a member of the enumeration [HealthBehaviorEnum](https://datacommons.org/browser/HealthBehaviorEnum){: target="_blank"}. The MCF would therefore look like this: ``` Node: dcid:who/Ratio_Smokers_Adolescents typeOf: schema:StatisticalVariable name: "Prevalence of current cigarette smoking among adolescents" description: "Percentage of all adolescents who are current cigarette smokers" populationType: dcid:Adolescents measuredProperty: dcid:Smoking statType: dcid:Ratio measurementDenominator: dcid:Count_Person_13To17Years Node: dcid:who/Ratio_Smokers_Adolescents_Female typeOf: schema:StatisticalVariable name: "Prevalence of current cigarette smoking among adolescents (female)" description: "Percentage of adolescents who are current cigarette smokers among all female adolescents" populationType: schema:Adolescents measuredProperty: dcid:Smoking statType: dcs:Ratio constraintProperties: dcid:gender gender: dcid:Female measurementDenominator: dcid:Count_Person_13To17Years_Female Node: dcid:who/Ratio_Smokers_Adolescents_Male typeOf: schema:StatisticalVariable name: "Prevalence of current cigarette smoking among adolescents (male)" description: "Percentage of adolescents who are current cigarette smokers among all male adolescents" populationType: schema:Adolescents measuredProperty: dcid:Smoking statType: dcs:Ratio constraintProperties: dcid:gender gender: dcid:Male measurementDenominator: dcid:Count_Person_13To17Years_Male ``` The order of nodes and fields within nodes does not matter. The following fields are always required: * `Node`: This is the DCID of the entity you are defining. DCIDs can be a maximum of 256 characters long. It must be preceded by the prefix `dcid:`. We recommend that you add an optional prefix, separated by a slash (/), for example, `who/`, to differentiate your custom variables from base DC variables. The prefix acts as a namespace, and should represent your organization, dataset, project, or whatever makes sense for you. > Note: If you plan to contribute your data to base Data Commons, DCIDs should follow the [DCID naming conventions](#naming). Otherwise, you can name them however you want. * `typeOf`: In the case of statistical variable, this is always `schema:StatisticalVariable`. * `name`: This is the descriptive name of the variable, that is displayed in the Statistical Variable Explorer and various other places in the UI. * `populationType`: This is the type of the thing being measured, and its value must be an existing `Class` or `Enumeration` type. In this example it is `schema:Person`. To get a full list of existing entity types, see the section on [searching](#search) above. If the thing you are measuring does not exist in the knowledge graph, you will need to create a new [entity type](custom_entities.md#entity-type) for it. * `measuredProperty`: This is a property of the thing being measured. It must be defined as a `schema:Property` of the `populationType` you have specified. In this example, it is the prevalence of smoking. The node [`Smoking`](https://datacommons.org/browser/Smoking){: target="_blank"} is a member of the [`HealthBehaviorEnum`](https://datacommons.org/browser/HealthBehaviorEnum){: target="_blank"}, which is a property of `Person`. To view the list of properties for a given `populationType`, use either of the following methods: * Go to
https://datacommons.org/browser/POPULATION_TYPE, e.g. https://api.datacommons.org/v2/node?key=AIzaSyCTI4Xz-UW_G2Q2RfknhcfdAnTHq5X5XuI&nodes=POPULATION_TYPE&property=%3C-domainIncludes, e.g. ./run_cdc_dev_docker.sh
docker run \
--env-file $PWD/custom_dc/env.list \
-v INPUT_DIRECTORY:INPUT_DIRECTORY \
-v OUTPUT_DIRECTORY:OUTPUT_DIRECTORY \
gcr.io/datcom-ci/datacommons-data:stable
docker run -it \
-p 8080:8080 \
-e DEBUG=true \
--env-file $PWD/custom_dc/env.list \
-v INPUT_DIRECTORY:INPUT_DIRECTORY \
-v OUTPUT_DIRECTORY:OUTPUT_DIRECTORY \
gcr.io/datcom-ci/datacommons-services:stable
./run_cdc_dev_docker.sh --schema_update
docker run \
--env-file $PWD/custom_dc/env.list \
-v INPUT_DIRECTORY:INPUT_DIRECTORY \
-v OUTPUT_DIRECTORY:OUTPUT_DIRECTORY \
-e DATA_RUN_MODE=schemaupdate
gcr.io/datcom-ci/datacommons-data:stable
docker run -it \
-p 8080:8080 \
-e DEBUG=true \
--env-file $PWD/custom_dc/env.list \
-v INPUT_DIRECTORY:INPUT_DIRECTORY \
-v OUTPUT_DIRECTORY:OUTPUT_DIRECTORY \
gcr.io/datcom-ci/datacommons-services:stable
sqlite3 OUTPUT_DIRECTORY/datacommons/datacommons.dbThis starts the interactive SQLite shell. To view a list of tables, at the prompt type `.tables`. The relevant table is `observations`. At the prompt, enter SQL queries. For example, for the sample OECD data, this query: ```shell sqlite> select * from observations limit 10; ``` returns output like this: ```shell country/BEL|average_annual_wage|2000|54577.62735|c/p/1 country/BEL|average_annual_wage|2001|54743.96009|c/p/1 country/BEL|average_annual_wage|2002|56157.24355|c/p/1 country/BEL|average_annual_wage|2003|56491.99591|c/p/1 country/BEL|average_annual_wage|2004|56195.68432|c/p/1 country/BEL|average_annual_wage|2005|55662.21541|c/p/1 ... ``` To exit the sqlite shell, press `Ctrl-D`.