Published
Edited
Insert cell
md`# Lab 2 - Working With Data in JavaScript (Template)`
Insert cell
md`
[Link to slides for this lab](https://docs.google.com/presentation/d/1LVvSGG0snk5R_-OdMJvIeeBmAzUGLZ9IZ2IiLHeCzCQ/edit?usp=sharing)

In this week's lab we'll be talking about how to use JavaScript and D3 to wrangle data. We'll be covering these topics in today's lab:

- Loading data using d3.csv
- Using d3 functions like min, max, mean
- Using JavaScript Array functions like map and filter
`
Insert cell
md`## Review of Anonymous functions`
Insert cell
md`Recall that in JavaScript there's 2 main ways to write anonymous functions. You either have Syntax 1: \`function() {}\` or Syntax 2 \`() => {}\`. Syntax 2 also has some variations - the most important one you should be aware of is this: \`param => param + 2\`. In this variation the second half of the expression is implicitly returned without using the return statement. In this case \`param + 2\` would be returned. Here are 3 different ways to write an anonymous function that finds the cube of a given number parameter:`
Insert cell
funcs = {
const syntax1 = function(num) {
return num * num * num;
};

const syntax2 = num => {
return num * num * num;
};

const syntax2a = num => num * num * num;

return syntax1(3) + syntax2(3) + syntax2a(3); // we should expect this to be 81 (27 + 27 + 27 = 81)
}
Insert cell
md`_Write an anonymous function that accepts a number as a parameter and returns its square in 3 different ways: 1. Using Syntax 1 2. Using Syntax 2 3. Using the one line variation of Syntax 2_`
Insert cell
squared = {
// functions here
}
Insert cell
md`## Loading Data`
Insert cell
md`We can use the d3.csv function to load data locally and from the internet. Let's use d3.csv to load a dataset about Pokemon and their stats. Use d3.csv to load [this data set from GitHub](https://gist.githubusercontent.com/armgilles/194bcff35001e7eb53a2a8b441e8b2c6/raw/92200bc0a673d5ce2110aaad4544ed6c4010f687/pokemon.csv). Remember to first [require](https://observablehq.com/@observablehq/introduction-to-require) d3.`
Insert cell
d3 = require('d3@5')
Insert cell
data = d3.csv(
"https://gist.githubusercontent.com/armgilles/194bcff35001e7eb53a2a8b441e8b2c6/raw/92200bc0a673d5ce2110aaad4544ed6c4010f687/pokemon.csv"
)
Insert cell
md`After you've loaded the data in, use \`render_data_table\` to display it as a table (it is already imported for you). You may want to [slice or make a smaller copy of](https://www.w3schools.com/jsref/jsref_slice_array.asp) the data before passing it to \`render_data_table\``
Insert cell
render_data_table(data.slice(0, 10))
Insert cell
md`## Using JavaScript Array functions`
Insert cell
md`JavaScript has many default array functions that you can use without importing anything. These functions are especially useful for manipulating data`
Insert cell
md`### map
This function performs an action on each element of the array and then returns a new array with the modified values. The parameter to this function __is also a function__. Here is an example:`
Insert cell
pokemon_names = data.map(d => {
return {
Name: d.Name,
Type: d['Type 1']
};
})
Insert cell
md`In the example above we passed the [anonymous function](https://www.w3schools.com/js/js_function_definition.asp)

\`\`\`
d => d.name
\`\`\`

Let's think about what our anonymous function does to one element in the original array. First, the element is passed as the parameter to our anonymous function. So in this case "d" is an Object with keys Name, Type, etc. Our anonymous function only returns or extracts the value of the name key. Applying this function to every Object in the original array we get an array of just pokemon names!

_Use the __map__ function to extract just the Attack of each Pokemon and store it in an array_
`
Insert cell
// extract an array of only pokemon attacks
pokemon_attacks = data.map(d => +d.Attack)
Insert cell
md`### filter
Often, we'll want to __filter__ the data based on some condition. For example, what if we want an array with only Pokemon that have an attack over 100? We can use the filter function to accomplish this:`
Insert cell
high_attack_pokemon = data.filter(d => d.Attack > 100)
Insert cell
md`The __filter__ function has a similar syntax to the map function. However, the anonymous function passed to the filter function __must__ return a boolean. _Use __filter__ to find __only the name__ of all pokemon who have a Defense higher than 150 (hint: you will need to use map as well)_`
Insert cell
high_defense = data
.filter(d => d.Defense > 150 && d.Attack > 100)
.map(d => d.Name)
Insert cell
md`JavaScript has many more useful Array utility functions but I find I end up using map and filter for almost every visualization I make. [Check out Mike's tutorial](https://observablehq.com/@info474/javascript-data-wrangling?collection=@info474/tutorials) for more useful Array functions.`
Insert cell
md`## D3 Array Utility Functions`
Insert cell
md`D3 also has some great methods for working with Arrays. Let's take a look at a few common ones`
Insert cell
md`### Min and Max`
Insert cell
md`D3 has two very useful functions which allow us to find the min and max of an array: min and max. Here is an example of how to use min and max with respect to the \`pokemon_attacks\` array:`
Insert cell
min_pokemon_atk = d3.min(pokemon_attacks)
Insert cell
max_pokemon_atk = d3.max(pokemon_attacks)
Insert cell
md`Another useful function which finds both the min and max of an array is \`extent\``
Insert cell
min_and_max_pokemon_atk = d3
.extent(pokemon_attacks)
Insert cell
md`These functions don't neccesarily need to be run on an array of numbers either. If we want to know the min and max Defense of all pokemon given only our initially loaded array of objects we can do this:`
Insert cell
min_max_pokemon_defense = d3.extent(data, d => +d.Defense)
Insert cell
md`This saves us the trouble of mapping just the defense of all pokemon to a new array`
Insert cell
md`_Find the min Total stats of a pokemon using only the array of objects you initially loaded in from d3.csv_`
Insert cell
// find min total
Insert cell
md`## Appendix`
Insert cell
import {
render_data_table,
table_styles,
displayImage,
displayCaution
} from "@info474/utilities"
Insert cell

One platform to build and deploy the best data apps

Experiment and prototype by building visualizations in live JavaScript notebooks. Collaborate with your team and decide which concepts to build out.
Use Observable Framework to build data apps locally. Use data loaders to build in any language or library, including Python, SQL, and R.
Seamlessly deploy to Observable. Test before you ship, use automatic deploy-on-commit, and ensure your projects are always up-to-date.
Learn more