Notebooks 2.0 is here.

Published
Edited
Apr 7, 2019
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
z = require('https://bundle.run/zebras@0.0.11') // specifying the library
Insert cell
Insert cell
md`
> \`\`\`javascript
df = [
{columnOne: 1, columnTwo: 'A'},
{columnOne: 2, columnTwo: 'B'}
]
\`\`\`
`
// This is the zebra representation --> An object is going to belong to a row. It is always an array of objects
// When you are importing a library with a d3 this is how it is boing to return your data
Insert cell
Insert cell
md`
> \`\`\`javascript
columnOne = [1, 2]
columnTwo = ['A', 'B']
\`\`\`
`

// This are the actual columns
Insert cell
Insert cell
rainAmounts = [
18.3,
19,
14.1
]
Insert cell
rainDates = Array.from({length: 3}, (_, i) => Date.now() - 1000 * 60 * 60 * 24 * i)
Insert cell
Insert cell
newRainfall = {
let rainArray = [] // empty array by putting empty square brackets and push elements to the areray (apend elements to the array) It is a container
for (var i=0; i<rainAmounts.length; i++) { // match the index of both arrays (because each has 3 elements)
let currRow = {rainAmount: rainAmounts[i], // construct a new object per row
date: rainDates[i]} // you can access the element by putting the index in the square brackets
rainArray.push(currRow) //every time you build a row, we want to add it to the array. With push we are storing every element to the array. it always goes to the end
}
return rainArray
}
Insert cell
rainfall = {
let rainDF = []
for (var i=0; i<rainAmounts.length; i++) {
rainDF.push({precipitation: rainAmounts[i], date: rainDates[i]})
}
return rainDF
}
Insert cell
Insert cell
daySeries = ["Monday", "Tuesday", "Wednesday"]
Insert cell
myNewDF = z.addCol("Day of the Week", daySeries, newRainfall) // series is an array, the last element is the dataframe
Insert cell
newRainfall // we did not modify the origial one, but created a new object with an added column in it. That is why we name the previous one "myNewDF" so we can access it later
Insert cell
z.addCol("day", daySeries, rainfall) // add col method is part of the zebras library so we use "z."
Insert cell
Insert cell
columns = Object.keys(rainfall[0])
Insert cell
Insert cell
shape = ({rows: rainfall.length, columns:Object.keys(rainfall[0]).length}) // the number of elements in the array is going to equal number of rows, number of properties = number of columns
Insert cell
Object.keys(newRainfall[0]).length // function that is going to take an object and is going to return a number of keys - an array of keys. Keys are column names.
Insert cell
Insert cell
Insert cell
migrationUrl = "https://gist.githubusercontent.com/cesandoval/b834ac93c07e03ec5205843b97f68017/raw/90951b60444376eebfcbbee9beca00c083f489f6/API_SM.POP.NETM_DS2_en_csv_v2_10473747.csv"
Insert cell
migration = d3.csv(migrationUrl) // method built into d3 that takes any csv files and turns it into an array of objects = df for zebras
Insert cell
Insert cell
Insert cell
Insert cell
z.head(5, migration) //5 = number of rows you want to inspect
Insert cell
z.head(20, migration) //20 = number of rows you want to inspect
Insert cell
z.tail(2, migration)// shows the last 2 rows
Insert cell
Insert cell
Insert cell
migration.length //length of the table = 264 rows
Insert cell
Insert cell
({rows: migration.length, columns:Object.keys(migration[0]).length}) // keys of number of columns
Insert cell
Insert cell
migrationColumns = Object.keys(migration[0])
Insert cell
Insert cell
Insert cell
Object.keys(migration[5])
Insert cell
migration[5] // 6th row
Insert cell
Object.values(migration[5]) // the number are strings!
Insert cell
firstRow = Object.values(migration[0]) // get the values of the first row
Insert cell
lastRow = Object.values(migration[migration.length-1])
Insert cell
randomRow = Object.values(migration[Math.floor(Math.random() * migration.length)])
Insert cell
Insert cell
Insert cell
numericalColumns = migrationColumns.slice(0, migrationColumns.length-4) //slice to separate the last 4 rows. Gives you all columns that have numbers in it
Insert cell
migrationParsed = z.parseNums(numericalColumns, migration) //parsNums takes an (array of columns, df)
// Now this is an array of numbers. Missing numbers are NaN - everything but the 4 last ones are numbers
Insert cell
Insert cell
z.head(5, migrationParsed)
Insert cell
Insert cell
countryName = z.getCol('Country Name', migrationParsed) // get col takes the name of the column and dataframe and it is going to return the column as an array
Insert cell
z.getCol('1962'.migrationParsed)
Insert cell
Insert cell
Insert cell
Insert cell
z.describe(z.getCol('1962', migrationParsed)) //z.describe is going to give you a series (array)
Insert cell
Insert cell
z.valueCounts(z.getCol('Indicator Code', migrationParsed)) // get unique values (e.g. 1,2,2 => returns 2, because there are 2 different values) in a given column that you provide
Insert cell
Insert cell
z.unique(z.getCol('Indicator Code', migrationParsed)) //unique = gives an array of those unique values "[1,2]"
Insert cell
Insert cell
Insert cell
function (row){
return row['1967'] > 500
}
Insert cell
z.filter( row => row['1967'] > 5000, migrationParsed) //arrow function is how zebras expect to operate. defining a variable name before accessing the elements of a function
// Only return the elements of row 1967 that are larger than 5000
// you are going on every element on the array which is a row. The name doesn't matter as long as you are consistent
// It is like a select statement
Insert cell
z.filter( row => row['1967'] > 500 && row['1962'] > 5000, migrationParsed)
Insert cell
z.filter( row => row['1964'] > 3000, migrationParsed)
Insert cell
z.filter( row => row['Country Name'] == 'Mexico', migrationParsed)
Insert cell
z.filter(r => r['1962'] > 0, migrationParsed)
Insert cell
Insert cell
z.filter(r => r['Country Name'] == "China", migrationParsed)
Insert cell
Insert cell
z.filter(r => r['1962'] > 0 && r['2012'] < 0, migrationParsed)
Insert cell
z.filter(r => r['1962'] > 0 && r['2012'] < 2000 && r['Country Name'] == 'United States', migrationParsed)
Insert cell
Insert cell
//We can use argument 'asc' to reverse the sorting
migrationSorted = z.sortByCol('2017', 'des', migrationParsed) // Sort by column function: des = descendant + Data Frame = migrationParsed
Insert cell
z.sortByCol('1962', 'asc', migrationParsed) // you are ordering the whole thing by column 1962 in a ascendant way
Insert cell
Insert cell
z.head(5, z.pickCols(['Country Name', '2017'], migrationSorted.slice(1)))
Insert cell
Insert cell
Insert cell
z.filter(r => r['Country Name'] == "Cayman Islands", migrationParsed) // We don't have values for this
Insert cell
z.filter(r => r['Country Name'] != "Cayman Islands", migrationParsed) // All the objects that are NOT Cayman Island
Insert cell
Insert cell
isNaN(z.getCol('1960', migrationParsed)[1]) //isNAN= checks if something is not a number
Insert cell
Type JavaScript, then Shift-Enter. Ctrl-space for more options. Arrow ↑/↓ to switch modes.

Insert cell
Insert cell
z.filter(r => Number.isNaN(r['1962']) == false, migrationParsed)
Insert cell
Insert cell
z.getCol('1960', migrationParsed)
Insert cell
Insert cell
z.dropCol(["1960"], migrationParsed)
Insert cell
Insert cell
Insert cell
migrationMetaUrl = "https://gist.githubusercontent.com/cesandoval/b834ac93c07e03ec5205843b97f68017/raw/90951b60444376eebfcbbee9beca00c083f489f6/Metadata_Country_API_SM.POP.NETM_DS2_en_csv_v2_10473747.csv"
Insert cell
migrationMeta = d3.csv(migrationMetaUrl)
Insert cell
Insert cell
migrationMeta.length
Insert cell
Insert cell
migrationMetaColumns = Object.keys(migrationMeta[0])
Insert cell
z.head(5, migrationMeta)
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
migration_join = z.merge(migrationParsed, migrationMeta, "Country Code", "Country Code", "_df1", "_df2")
// migration_join = migrationParsed.map(x => Object.assign(x, migrationMeta.find(y => y['Country Code'] == x['Country Code'])));
Insert cell
Insert cell
Insert cell
migration_2017 = z.getCol('2017', migration_join)
Insert cell
z.print([
{
minMigration: z.min(migration_2017).toFixed(5),
maxMigration: z.max(migration_2017).toFixed(5),
meanMigration: z.mean(migration_2017).toFixed(5),
medianMigration: z.median(migration_2017).toFixed(5),
stdMigration: z.std(migration_2017).toFixed(5)
}
])
Insert cell
Insert cell
migration_2017_Piped = z.pipe(
[
z.parseNums(['1992','1997','2002','2007', '2012', '2017']),
z.getCol('2017'),
z.mean()
]
)(migration_join)
// .pipe = if you don't want to create a variable every time you call a function you can pipe them together - chain operations together so every line is not creating a new object
Insert cell
Insert cell
migrationByRegion = z.groupBy(x=>x.Region_df1, migration_join) // returns a new data frame grouped by different regions
Insert cell
Insert cell
migrationCountRegion = z.gbCount("Region", migrationByRegion)
Insert cell
Insert cell
Insert cell
Insert cell
d3 = require("d3")
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more