Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Exposes US County Data #83

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ Notice that most countries follow a similar straight line path, indicating that

## Credits

This interactive pulls data on COVID-19 provided by [Johns Hopkins CSSE](https://github.com/CSSEGISandData/COVID-19) and <a href="https://github.com/nytimes/covid-19-data">NYTimes</a>. Huge thanks to them for making this invaluable data source publicly available.
This interactive pulls data on COVID-19 provided by [Johns Hopkins CSSE](https://github.com/CSSEGISandData/COVID-19). Huge thanks to them for making this invaluable data source publicly available.

Created by [Aatish Bhatia](https://aatishb.com/) in collaboration with [Henry Reich](https://www.youtube.com/user/minutephysics).

Expand Down Expand Up @@ -74,5 +74,5 @@ If you would like to participate or contribute, please read our [Contributor's G

Code in this repository which is not otherwise licensed is licensed under the MIT License; see [LICENSE.txt](LICENSE.txt) for complete text.

This repository pulls data from [2019 Novel Coronavirus COVID-19 (2019-nCoV) Data Repository by Johns Hopkins CSSE](https://github.com/CSSEGISandData/COVID-19) and [New York Times Coronavirus (Covid-19) Data in the United States](https://github.com/nytimes/covid-19-data#license-and-attribution). Please consult these repositories for terms of use on the data.
This repository pulls data from [2019 Novel Coronavirus COVID-19 (2019-nCoV) Data Repository by Johns Hopkins CSSE](https://github.com/CSSEGISandData/COVID-19). Please consult these repositories for terms of use on the data.

8 changes: 7 additions & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ <h2>{{ formatDate(minDay > 0 ? dates[day - 1] : dates[dates.length - 1]) }}</h2>
<div v-if="!firstLoad && covidData.length == 0" id="nodata"><span>Not enough data for these parameters.</span></div>

<div id="footer">
Created by <a href="https://aatishb.com/">Aatish Bhatia</a> in collaboration with <a href="https://www.youtube.com/user/minutephysics">Minute Physics</a> &middot; World data provided by <a href="https://github.com/CSSEGISandData/COVID-19">Johns Hopkins University</a> (updated daily around 00:00 UTC / 20:00 ET) &middot; US state data provided by <a href="https://github.com/nytimes/covid-19-data">NYTimes</a> (updated daily around 16:00 UTC / 12:00 ET)&middot; Shortcuts: +/- for daily changes, space to play/pause &middot; <a href="https://github.com/aatishb/covidtrends#credits">Credits & Source</a> &middot; <a href="https://www.cdc.gov/coronavirus/2019-ncov/prepare/prevention.html">Stay safe!</a>
Created by <a href="https://aatishb.com/">Aatish Bhatia</a> in collaboration with <a href="https://www.youtube.com/user/minutephysics">Minute Physics</a> &middot; World data provided by <a href="https://github.com/CSSEGISandData/COVID-19">Johns Hopkins University</a> (updated daily around 00:00 UTC / 20:00 ET) &middot; Shortcuts: +/- for daily changes, space to play/pause &middot; <a href="https://github.com/aatishb/covidtrends#credits">Credits & Source</a> &middot; <a href="https://www.cdc.gov/coronavirus/2019-ncov/prepare/prevention.html">Stay safe!</a>
</div>

</div>
Expand All @@ -116,6 +116,12 @@ <h2>Customize</h2>
</option>
</select>

<select v-model="selectedState" @mousedown="pause" v-if="selectedRegion == 'US Counties'">
<option v-for="s in states" v-bind:value="s">
{{ s }}
</option>
</select>

<select v-model="selectedScale" @mousedown="pause">
<option v-for="s in scale" v-bind:value="s">
{{ s }}
Expand Down
125 changes: 95 additions & 30 deletions vue-definitions.js
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ let app = new Vue({
el: '#root',

mounted() {
this.pullData(this.selectedData, this.selectedRegion);
this.pullData(this.selectedData, this.selectedRegion, this.selectedState);
},

created: function() {
Expand Down Expand Up @@ -175,6 +175,13 @@ let app = new Vue({
}
}

if (urlParameters.has('state')) {
let myState = urlParameters.get('state');
if (this.states.includes(myState)) {
this.selectedState = myState;
}
}

// since this rename came later, use the old name to not break existing URLs
let renames = {
'China': 'China (Mainland)'
Expand Down Expand Up @@ -214,14 +221,21 @@ let app = new Vue({
watch: {
selectedData() {
if (!this.firstLoad) {
this.pullData(this.selectedData, this.selectedRegion, /*updateSelectedCountries*/ false);
this.pullData(this.selectedData, this.selectedRegion, this.selectedState, /*updateSelectedCountries*/ false);
}
this.searchField = '';
},

selectedRegion() {
if (!this.firstLoad) {
this.pullData(this.selectedData, this.selectedRegion, /*updateSelectedCountries*/ true);
this.pullData(this.selectedData, this.selectedRegion, this.selectedState, /*updateSelectedCountries*/ true);
}
this.searchField = '';
},

selectedState() {
if (!this.firstLoad) {
this.pullData(this.selectedData, this.selectedRegion, this.selectedState, /*updateSelectedCountries*/ true);
}
this.searchField = '';
},
Expand Down Expand Up @@ -284,22 +298,33 @@ let app = new Vue({
return Math.min.apply(Math, par);
},

pullData(selectedData, selectedRegion, updateSelectedCountries = true) {

if (selectedRegion != 'US') {
let url;
pullData(selectedData, selectedRegion, selectedState, updateSelectedCountries = true) {
// Construct URL
let url;
if (selectedRegion.startsWith('US')) { // Use US Data
if (selectedData == 'Confirmed Cases') {
url = 'https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_time_series/time_series_covid19_confirmed_US.csv';
} else if (selectedData == 'Reported Deaths') {
url = 'https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_time_series/time_series_covid19_deaths_US.csv';
}
} else { // Use Global Data
if (selectedData == 'Confirmed Cases') {
url = 'https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_time_series/time_series_covid19_confirmed_global.csv';
} else if (selectedData == 'Reported Deaths') {
url = 'https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_time_series/time_series_covid19_deaths_global.csv';
} else {
return;
}
Plotly.d3.csv(url, (data) => this.processData(data, selectedRegion, updateSelectedCountries));
} else { // selectedRegion == 'US'
const type = (selectedData == 'Reported Deaths') ? 'deaths' : 'cases'
const url = 'https://raw.githubusercontent.com/nytimes/covid-19-data/master/us-states.csv';
Plotly.d3.csv(url, (data) => this.processData(this.preprocessNYTData(data, type), selectedRegion, updateSelectedCountries));
}

// Pull Data
if (url) {
switch (this.selectedRegion) {
case 'US States':
return Plotly.d3.csv(url, (data) => this.processData(this.preprocessUSStateData(data), selectedRegion, selectedState, updateSelectedCountries));
case 'US Counties':
return Plotly.d3.csv(url, (data) => this.processData(this.preprocessUSCountyData(data, selectedState), selectedRegion, selectedState, updateSelectedCountries));
default:
return Plotly.d3.csv(url, (data) => this.processData(data, selectedRegion, selectedState, updateSelectedCountries));
}
}
},

Expand Down Expand Up @@ -344,7 +369,7 @@ let app = new Vue({
.map(e => Object.assign({}, e, {region: e['Province/State']}));
},

processData(data, selectedRegion, updateSelectedCountries) {
processData(data, selectedRegion, selectedState, updateSelectedCountries) {
let dates = Object.keys(data[0]).slice(4);
this.dates = dates;
this.day = this.dates.length;
Expand All @@ -364,12 +389,16 @@ let app = new Vue({
}
}

} else if (selectedRegion == 'US States') {
grouped = this.filterByCountry(data, dates, 'US');
} else if (selectedRegion == 'US Counties') {
grouped = this.filterByCountry(data, dates, selectedState);
} else {
grouped = this.filterByCountry(data, dates, selectedRegion)
.filter(e => !regionsToPullToCountryLevel.includes(e.region)); // also filter our Hong Kong and Macau as subregions of Mainland China
}

let exclusions = ['Cruise Ship', 'Diamond Princess'];
let exclusions = ['Cruise Ship', 'Diamond Princess', 'Grand Princess', 'Unassigned'];

let renames = {
'Taiwan*': 'Taiwan',
Expand Down Expand Up @@ -423,18 +452,38 @@ let app = new Vue({

},

preprocessNYTData(data, type) {
let recastData = {};
data.forEach(e => {
let st = recastData[e.state] = (recastData[e.state] || {'Province/State': e.state, 'Country/Region': 'US', 'Lat': null, 'Long': null});
st[fixNYTDate(e.date)] = parseInt(e[type]);
preprocessUSCountyData(data, selectedState) {
let result = {};
data.filter(r => r.Province_State == selectedState).forEach(record => {
let state = record.Province_State
let county = record.Admin2
let temp = (result[county] || {'Province/State': county, 'Country/Region': state, 'Lat': null, 'Long': null})
Object.keys(record).forEach(key => {
// if they key starts with a digit we assume it is a date
if (/^\d/.test(key)) {
temp[key] = parseInt(record[key])
}
});
result[county] = temp
});
return Object.values(recastData);

function fixNYTDate(date) {
let tmp = date.split('-');
return `${tmp[1]}/${tmp[2]}/${tmp[0].substr(2)}`;
}
return Object.values(result);
},

preprocessUSStateData(data) {
let result = {};
data.forEach(record => {
let state = record.Province_State
let temp = (result[state] || {'Province/State': state, 'Country/Region': 'US', 'Lat': null, 'Long': null})
Object.keys(record).forEach(key => {
// if they key starts with a digit we assume it is a date
if (/^\d/.test(key)) {
// each record is a county so we sum them up to get the state wide total
temp[key] = (temp[key] || 0) + parseInt(record[key])
}
});
result[state] = temp
});
return Object.values(result);
},

formatDate(date) {
Expand Down Expand Up @@ -522,6 +571,10 @@ let app = new Vue({
queryUrl.append('region', this.selectedRegion);
}

if (this.selectedRegion == 'US Counties' && this.selectedState != 'Alabama') {
queryUrl.append('state', this.selectedState);
}

// since this rename came later, use the old name for URLs to avoid breaking existing URLs
let renames = {
'China (Mainland)': 'China'
Expand Down Expand Up @@ -592,8 +645,10 @@ let app = new Vue({
case 'World':
return 'Countries';
case 'Australia':
case 'US':
return 'States';
case 'US States':
return 'States and Territories';
case 'US Counties':
return 'Counties';
case 'China':
return 'Provinces';
case 'Canada':
Expand Down Expand Up @@ -736,10 +791,20 @@ let app = new Vue({

selectedData: 'Confirmed Cases',

regions: ['World', 'US', 'China', 'Australia', 'Canada'],
regions: ['World', 'US States', 'US Counties', 'China', 'Australia', 'Canada'],

selectedRegion: 'World',

states: ['Alabama', 'Alaska', 'Arizona', 'Arkansas', 'California', 'Colorado', 'Connecticut', 'Delaware',
'District of Columbia', 'Florida', 'Georgia', 'Guam', 'Hawaii', 'Idaho', 'Illinois', 'Indiana', 'Iowa',
'Kansas', 'Kentucky', 'Louisiana', 'Maine', 'Maryland', 'Massachusetts', 'Michigan', 'Minnesota',
'Mississippi', 'Missouri', 'Montana', 'Nebraska', 'Nevada', 'New Hampshire', 'New Jersey', 'New Mexico',
'New York', 'North Carolina', 'North Dakota', 'Northern Mariana Islands', 'Ohio', 'Oklahoma', 'Oregon',
'Pennsylvania', 'Puerto Rico', 'Rhode Island', 'South Carolina', 'South Dakota', 'Tennessee', 'Texas',
'Utah', 'Vermont', 'Virgin Islands', 'Virginia', 'Washington', 'West Virginia', 'Wisconsin', 'Wyoming'],

selectedState: 'Alabama',

sliderSelected: false,

day: 7,
Expand Down