├── .gitignore ├── 2018-03-approval-ratings ├── approval-ratings.R └── readme.md ├── 2019-02-bechdel-test ├── README.md ├── package.json └── script.js ├── 2019-03-ngrams-for-all-corpora ├── README.md ├── example-csv │ └── all-1945.csv ├── make-ngrams.sh ├── makefile └── ngram.py ├── 2019-06-greenland-ice-melting ├── README.md ├── data.csv └── script.R ├── 2019-11-api-updates ├── Readme.md ├── deno.script.js ├── lib │ └── dotenv.js └── script.js ├── 2020-02-06-temperature-chart ├── january-temp-range.csv └── plot.R ├── 2020-03-coronavirus-charts ├── README.md └── coronavirus.R ├── 2020-04-02-website-colors ├── .gitignore ├── README.md ├── requirements.txt └── website_colors.py ├── 2020-04-30-most-expensive-records ├── README.md ├── create_final100.js ├── download_images.js ├── export.js ├── get_monthly_posts.js ├── get_top100_post.js └── package.json ├── 2020-05-28-excess-mortality ├── 2020-05-26_stmf_raw.xlsx ├── README.md ├── aut-excess-mortality.R ├── bel-excess-mortality.R ├── covid19-mortality.Rproj ├── data │ ├── aut.csv │ ├── bel.csv │ ├── esp.csv │ ├── ger.csv │ ├── nyc.csv │ ├── swe.csv │ └── usa.csv ├── esp-excess-mortality.R ├── ger-excess-mortality.R ├── nyc-excess-mortality.R ├── swe-excess-mortality.R └── usa-excess-mortality.R ├── 2020-09-10-ridgeline-plot ├── README.md ├── pulsar_sorted.csv └── script.js ├── 2020-10-18-trump-tweet-heatmap ├── .env-template ├── README.md ├── count-tweets.js ├── create-heatmap.js ├── data │ ├── all-tweets.json │ ├── chart-data.csv │ ├── daily-tweets.json │ ├── previous-year-tweets.json │ └── tweet-stats.json ├── get-stats.js ├── get-tweets.js ├── package-lock.json ├── package.json ├── trump-tweet-heatmap.png └── utils │ ├── dw-api-utils.js │ └── utils.js ├── 2021-05-27-weather-forecast ├── .gitignore ├── README.md ├── forecast.csv └── weather-forecast-table.R ├── 2021-06-17-game-of-life ├── README.md ├── api_script.js ├── csv_script.js ├── game-of-life.gif └── package.json ├── 2021-08-05-summer-winter-olympics-temperature ├── ellipse-jitter.R └── readme.md ├── 2021-09-27-Australia-share-75years └── Australia-LGA-share-75-or-older.csv ├── 2022-01-06-function-names ├── .ipynb_checkpoints │ └── notebook-checkpoint.ipynb ├── form.csv ├── google_form.png ├── notebook.ipynb └── result.csv ├── 2022-06-30-background-colors ├── 808s-heartbreak.png ├── Screenshot 2022-06-30 at 10.28.31.png ├── a-life-on-the-plannet.png ├── a-snapshot-of-tate-museums.png ├── a-story-about-hearing-yourself-represented-with-same-gender-lyrics-for-the-first-time.png ├── an-open-question-survey.png ├── apple-music-rapped.png ├── art.png ├── arts-blooming-in-ohio.png ├── best-animated-movies.png ├── campaign-colors.png ├── can-data-die.png ├── climate-change-by-generation.png ├── clubbing-feels.png ├── college-spirit-songs.png ├── colors-of-van-gogh.png ├── colour-symbolism-in-the-great-gatsby.png ├── comedy-in-huntsville.png ├── compositions-of-ludwig-van-beethoven.png ├── counting-the-cost-of-the-education-revolution.png ├── creating-demand-for-digital-art.png ├── crypto-art.png ├── de-tijd-background-color.png ├── detailed-analysis-of-movies.png ├── do-women-speak-to-each-other.png ├── egot.png ├── financial-times-background-color.png ├── following-the-science.png ├── frontliner.png ├── gallup-background-color.png ├── getting-creative-with-the-economy.png ├── good-teachers-are-kind.png ├── guest-on-the-ellen-degeneres-show.png ├── hamilton.png ├── health-care-journey.png ├── how-encanto-songs-make-me-feel.png ├── how-kerala’s-dams-failed-to-prevent-catastrophe.png ├── how-music-is-remembered.png ├── how-officer-complaints-are-investigated.png ├── how-to-make-a-hit-movie.png ├── how-you-play-spades-is-how-you-play-life.png ├── james-bond-movie-franchise.png ├── james-bond-theme-song.png ├── last-words.png ├── lebron-james-fan-favorite.png ├── lightning-cost.png ├── live-music-analyst.png ├── masculinity.png ├── measuring-radio's-lag-behind-streaming-services.png ├── mike-and-tom-eat-snacks.png ├── netflix-oscars-viz.png ├── new-america-background-color.png ├── next-to-normal.png ├── nft---digital-art.png ├── ode-to-cinema.png ├── oreos-and-the-art-of-crossword-puzzle-construction.png ├── palette-of-art.png ├── pixar-in-theaters.png ├── putin-world-address.png ├── rambling-through-the-avenues-of-time.png ├── rats.png ├── reading-habits.png ├── remote-work-survey.png ├── rothko-artworks-at-the-national-gallery-of-art.png ├── saroj-khan.png ├── sherlock-holmes.png ├── sourav-karwa-spotify-weekly-top-200.png ├── space-junk.png ├── spotify-top-50-songs.png ├── spotify.png ├── stand-out-of-the-shadows.png ├── streaming-service-comparisons.png ├── sweet-slim-greasy-grim.png ├── taylor-swift.png ├── the-art-of-conversation.png ├── the-art-of.png ├── the-arts-in-singapore.png ├── the-beat-lives-on.png ├── the-buran.png ├── the-discography-of-deadmau5.png ├── the-economist-new.png ├── the-economist-old.png ├── the-faces-of-a-nation.png ├── the-firebird-suite.png ├── the-funniest-ted-talks.png ├── the-genres-of-acl.png ├── the-rise-of-nft-art.png ├── the-singlit-movement.png ├── the-times-background-color.png ├── the-vast-legacy-and-miserable-life-of-vincent-van-gogh.png ├── thearttheartist.png ├── this-is-an-experiment-about-how-we-view-history.png ├── top-popular-movies.png ├── vincent-van-gogh-letters.png ├── visualisation-of-arts.png ├── was-yesterday-a-heat-record.png ├── we-couldn’t-get-an-artificial-intelligence-program-to-win-the-new-yorker-caption-contest.png ├── we-found-this-cool-study-about-randomness.png ├── when-women-make-headlines.png ├── whos-in-your-wallet.png ├── why-are-k-pop-groups-so-big.png ├── wine-and-math.png └── women-in-film.png ├── 2023-11-R-demo ├── R-script ├── README.md └── daily-temperatures-potsdam.png ├── LICENSE └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | *.pid.lock 13 | 14 | # Directory for instrumented libs generated by jscoverage/JSCover 15 | lib-cov 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage 19 | 20 | # nyc test coverage 21 | .nyc_output 22 | 23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 24 | .grunt 25 | 26 | # Bower dependency directory (https://bower.io/) 27 | bower_components 28 | 29 | # node-waf configuration 30 | .lock-wscript 31 | 32 | # Compiled binary addons (https://nodejs.org/api/addons.html) 33 | build/Release 34 | 35 | # Dependency directories 36 | node_modules/ 37 | jspm_packages/ 38 | 39 | # TypeScript v1 declaration files 40 | typings/ 41 | 42 | # Optional npm cache directory 43 | .npm 44 | 45 | # Optional eslint cache 46 | .eslintcache 47 | 48 | # Optional REPL history 49 | .node_repl_history 50 | 51 | # Output of 'npm pack' 52 | *.tgz 53 | 54 | # Yarn Integrity file 55 | .yarn-integrity 56 | 57 | # dotenv environment variables file 58 | .env 59 | 60 | # next.js build output 61 | .next 62 | .Rproj.user 63 | -------------------------------------------------------------------------------- /2018-03-approval-ratings/approval-ratings.R: -------------------------------------------------------------------------------- 1 | needs(dplyr, tidyr, readr, jsonlite) 2 | 3 | trump_ratings <- read_csv('https://projects.fivethirtyeight.com/trump-approval-data/approval_topline.csv') %>% 4 | filter(subgroup=='All polls') %>% 5 | mutate(date=as.Date(modeldate, format='%m/%d/%Y'), 6 | approve=as.numeric(approve_estimate), 7 | disapprove=as.numeric(disapprove_estimate)) %>% 8 | select(date, approve, disapprove, president) 9 | 10 | ratings <- read_json('https://projects.fivethirtyeight.com/trump-approval-data/historical-approval.json', T) %>% 11 | mutate(date=as.Date(date), 12 | approve=as.numeric(approve_estimate), 13 | disapprove=as.numeric(disapprove_estimate))%>% 14 | select(date, approve, disapprove, president) %>% 15 | bind_rows(trump_ratings) %>% 16 | group_by(date=as.Date(paste0(format(date, '%Y-%m'),'-01'))) %>% 17 | summarise(president=last(president), approve=mean(approve), disapprove=mean(disapprove)) 18 | 19 | ratings %>% 20 | select(date, president, approve) %>% 21 | filter(date>='1961-02-01') %>% 22 | mutate(president=as.factor(as.character(president))) %>% 23 | spread(president, approve) %>% 24 | write_tsv('ratings.csv', na = '') 25 | -------------------------------------------------------------------------------- /2018-03-approval-ratings/readme.md: -------------------------------------------------------------------------------- 1 | # presidential approval ratings 2 | 3 | this is the [R script used to scrape the data](https://github.com/datawrapper/snippets/blob/master/2018-03-approval-ratings/approval-ratings.R) from FiveThirtyEight.com for this chart: 4 | 5 | ![line chart of US presidential approval ratings since Kennedy](https://img.datawrapper.de/Wa2Ci/full.png) 6 | 7 | related links: 8 | 9 | * [interactive chart](https://datawrapper.dwcdn.net/Wa2Ci/16/) 10 | * [reddit discussion](https://www.reddit.com/r/dataisbeautiful/comments/88080t/presidential_approval_ratings_since_kenney_oc/) 11 | -------------------------------------------------------------------------------- /2019-02-bechdel-test/README.md: -------------------------------------------------------------------------------- 1 | # Bechdel test 2 | 3 | This [node.js script](https://github.com/datawrapper/snippets/blob/master/2019-02-bechdel-test/script.js) does the following: 4 | 5 | 1. takes data obtained through the [Bechdel test website API](https://bechdeltest.com/api/v1/doc) (data can be obtained by running `curl http://bechdeltest.com/api/v1/getAllMovies > data.json`) 6 | 2. groups films by decade 7 | 3. calculates the percentage of films that pass different number of Bechdel test criteria for each decade 8 | 4. converts data to `CSV` 9 | 10 | The following chart was created using the output data: 11 | 12 | ![Percentage of films that pass the Bechdel test is rising](https://img.datawrapper.de/Ztmoc/full.png) 13 | 14 | ### Related links 15 | 16 | * [Interactive chart](https://www.datawrapper.de/_/Ztmoc/) 17 | * [Weekly chart article](https://blog.datawrapper.de/weeklychart-bechdel-test/) 18 | 19 | ### Notes 20 | 21 | You need to have [node.js](https://nodejs.org/en/) and [npm](https://www.npmjs.com/) installed on your system in order to run this script. Install required packages first by running `npm i`. Execute the script by running `node script.js`. 22 | -------------------------------------------------------------------------------- /2019-02-bechdel-test/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bechdel-test", 3 | "version": "1.0.0", 4 | "description": "Script to convert data obtained from the Bechdel test website", 5 | "main": "script.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "Ivan Lokhov", 10 | "dependencies": { 11 | "underscore": "^1.9.1" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /2019-02-bechdel-test/script.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const _ = require('underscore'); 3 | 4 | fs.readFile('data.json', (err, data) => { 5 | if (err) throw err; 6 | 7 | const json = JSON.parse(data); 8 | 9 | const decades = _.groupBy(json, film => { 10 | return film.year.substring(0, 3); 11 | }); 12 | 13 | // write first line 14 | let csvText = 'Decade,3 of 3,2 of 3,1 of 3,0 of 3\n'; 15 | 16 | Object.keys(decades).forEach(decade => { 17 | const films = decades[decade]; 18 | const total = films.length; 19 | const ratings = _.countBy(films, film => { 20 | return film.rating; 21 | }); 22 | 23 | Object.keys(ratings).map(rating => { 24 | ratings[rating] = (ratings[rating] / total * 100).toFixed(1); 25 | }); 26 | 27 | const line = `${decade}0s,${ratings[3] || null},${ratings[2] || null},${ratings[1] || null},${ratings[0] || null}\n`; 28 | csvText += line; 29 | }); 30 | 31 | // write to file 32 | fs.writeFile('bechdel.csv', csvText, (err) => { 33 | if (err) throw err; 34 | }); 35 | }); 36 | -------------------------------------------------------------------------------- /2019-03-ngrams-for-all-corpora/README.md: -------------------------------------------------------------------------------- 1 | 2 | # Comparison of ngrams in different corpora 3 | 4 | *"Corpora" is the plural of "corpus", like the Russian book corpus or the German book corpus. [Learn more about Google ngrams here](https://books.google.com/ngrams).* 5 | 6 | ## What does it do? 7 | 8 | The code in this repo is great if you want to find out **how often the same words (or numbers) were used in books written in different languages, historically.** It runs [Matt Nicklay](https://github.com/econpy)'s [google-ngrams](https://github.com/econpy/google-ngrams) script for different corpora and joins them all together as one csv. 9 | 10 | ## How does it work? 11 | 12 | 1. `git clone` this repo. 13 | 2. Open the `makefile` and write down the queries you want to run. 14 | 3. Open the `make-ngrams.sh` bash script and specify the corpora, the end year, the start year and everything else the [google-ngrams script](https://github.com/econpy/google-ngrams) lets you specify (Matt wrote a good readme explaining that). 15 | 4. Open your terminal, navigate to the folder and type `make` (or `make ngram`). 16 | 5. Wait. Then celebrate your final csv. 17 | 18 | The following thing will happen once you type `make`: 19 | 20 | ![](https://i.imgur.com/wQc2Ihf.gif) 21 | 22 | ## Output 23 | ...is a csv that looks like this: 24 | 25 | ![](https://i.imgur.com/0UDAL0y.png) 26 | 27 | ## Related links 28 | not yet up! 29 | -------------------------------------------------------------------------------- /2019-03-ngrams-for-all-corpora/example-csv/all-1945.csv: -------------------------------------------------------------------------------- 1 | year,eng_gb_2012,eng_us_2012,fre_2012,ger_2012,heb_2012,rus_2012,spa_2012 2 | 1930,8.750866840046001E-7,7.110400019882945E-7,0.0000011460899713711115,0.0000011187504469489795,1.0517936388509952E-7,0.0000012456195008780924,0.0000013985177815811767 3 | 1931,7.342947393832825E-7,7.177777850605102E-7,0.0000015659674469740519,9.764443689164182E-7,7.011957592339968E-8,0.0000031350634799309773,0.0000012405533311721229 4 | 1932,4.2409005610958655E-7,8.863073617249029E-7,0.000001465274389526409,8.656843040929137E-7,6.450709075049114E-7,0.000004368333861748397,0.0000010356940075932168 5 | 1933,6.625742040948049E-7,9.086838114550725E-7,0.0000011375939739840153,7.336813799459682E-7,6.129317095352841E-7,0.000004178085362127604,0.0000013267421271242104 6 | 1934,0.0000010015425857545779,0.0000015196137420995608,7.076006814562182E-7,0.0000012468107684071583,0.0000011504246610153739,0.000002671088717913032,0.000001411817834195972 7 | 1935,0.0000011313758629209285,0.0000015175294076167727,9.580809224492743E-7,0.0000015450632796879897,5.582689605413785E-7,0.0000024206420713805223,0.0000013126778715862504 8 | 1936,0.0000010117153124156175,0.0000027086345729306536,0.0000011929051121721084,0.000001700936233343479,5.790996174444748E-7,0.0000028164627868439616,0.0000014957623761802097 9 | 1937,8.750298926922065E-7,0.0000026980372922480456,0.0000015787400874008501,0.0000012665851537955557,2.075393889337344E-7,0.0000027736111860576784,0.000001777777280646357 10 | 1938,0.0000014646829337531624,0.0000029169120049724975,0.000004661455970259946,0.0000011647192081909452,4.383294438525809E-7,0.000002022853209382447,0.000002134468066590974 11 | 1939,0.0000022678696041111834,0.0000026661505216907244,0.000012222270318792047,0.0000016747475418317965,5.962287824938054E-7,0.0000023979213968535382,0.000003581490394329497 12 | 1940,0.0000036346528607585546,0.0000029736096015161215,0.00001323578665809085,0.0000017576396279158264,6.107766807872395E-7,0.000006100626971298577,0.000005445330619598583 13 | 1941,0.000003939653121657709,0.000005406200898505631,0.000012770363052065173,0.0000020929389089966812,7.704427389398916E-7,0.000007906491418907535,0.0000068083128705135705 14 | 1942,0.000005189497566486049,0.000007554956710009719,0.00001484560622581436,0.0000028594508876267355,0.000001774216154141565,0.000010784621887675408,0.000011339794582454488 15 | 1943,0.000007166494848812969,0.000011361611844525518,0.00003598696184781147,0.000007515475014467181,0.00000575049405900548,0.000014776815836133514,0.00002506139981051092 16 | 1944,0.000020605960192672985,0.00003467266560619464,0.00012998500278627034,0.00006001196091650248,0.00001615454849949553,0.00017456903212102284,0.00010976998540475809 17 | 1946,0.00005329960307183986,0.00009342913108412176,0.0002321602078154683,0.0001510496852764239,0.00003165471874429689,0.00026678054079335806,0.00020705685407544175 18 | 1947,0.00006249558161168049,0.00010155294148717076,0.00018272608576808125,0.00013698983578554666,0.00002753709062138417,0.0001263299200218171,0.00015386350181264183 19 | 1948,0.00006587099657432798,0.00010584459717695911,0.0001404170470777899,0.00012126356402101617,0.000025592500605853274,0.00007418491198526074,0.00011265291929400216 20 | 1949,0.00006401797872968018,0.00010037178920659547,0.00012620473717106506,0.00012152661414196093,0.00001870923309373514,0.00006564039358636364,0.00008888980664778501 21 | 1950,0.00005661848384382514,0.0000963192845423085,0.00011366218192658077,0.00012483741496301567,0.000016589108781772666,0.00006209575318886588,0.00007795527199050412 22 | 1951,0.00004902110110075834,0.0000886992274899967,0.00011098186223534867,0.0001252685518314441,0.000015138473221062062,0.00005770270096642586,0.00006981522892601788 23 | 1952,0.00004960263928902956,0.00008487750407463561,0.0001032980532424214,0.00012295565102249384,0.00001382444800886636,0.0000498471466319946,0.00006518743612105027 24 | 1953,0.00005008268514454054,0.00008008666191017255,0.00009909803823878367,0.00011925898919192453,0.000012603660858682511,0.00005071324630989693,0.0000604451658243003 25 | 1954,0.00005135302490089089,0.00007733914389973506,0.00009059162888055046,0.0001215542433783412,0.000013527725665577842,0.000049542739967970796,0.00006032853707438335 26 | 1955,0.00004915274015123335,0.0000734042696421966,0.00008433777596413468,0.00012185324643117686,0.000011356787581462413,0.00004679405174101703,0.000057141877429482214 27 | 1956,0.00004860904179319429,0.00006731216126354411,0.00007836282262966658,0.00011906293123805274,0.000010835468250055177,0.000043843452052290864,0.00005499300823430531 28 | 1957,0.00004625094879884273,0.00006122653091248746,0.0000727570804883726,0.00011048963157615314,0.000009696886081655975,0.000045070073004656784,0.00004927443660562858 29 | 1958,0.000045912654362230874,0.000056076484421888985,0.0000668420495154957,0.00010842762518829356,0.000010708221452659927,0.00004560541250005675,0.000047071462176973 30 | 1959,0.00004452099892660044,0.00005282503722507196,0.00006122143167885952,0.00011116312331675242,0.00001209095656425537,0.00004412097890356866,0.00004298043738041694 31 | 1960,0.00004448144924632894,0.000050165021093562245,0.00005662676630890928,0.0001168854214483872,0.000014038517292647157,0.000042234070861013606,0.00004049617321773743 32 | 1961,0.00004342458851169795,0.000049428507433428116,0.000054261015369168795,0.00011236261343583465,0.000013556020045749998,0.00004174188385756376,0.00003712853019048149 33 | 1962,0.00004231298225931823,0.00004794100944612486,0.00005147149083010542,0.00010521142879345764,0.000012620929131420175,0.000039751270378474146,0.0000374449446098879 34 | 1963,0.00004327551747943895,0.00004558452686372524,0.000051753532413082816,0.0000995669252006337,0.000010102783562615514,0.00003953344154676112,0.00003586260208976455 35 | 1964,0.000042739216344974316,0.000042938236826254674,0.0000509702367708087,0.00009988197901596625,0.000010181404225780474,0.000041309552519426994,0.00003627774276537821 36 | 1965,0.00004365069617051631,0.00004264756595754685,0.00005060178227722645,0.00010283265146426857,0.000010022874751787944,0.00004031143786657291,0.00003603202761344922 37 | 1966,0.000041063571795045085,0.00004200607266587516,0.000048585257900413126,0.0000982508451367418,0.000008997617442219052,0.000040466881425042324,0.00003523331421699064 38 | 1967,0.000040775921661406755,0.00004019281671692928,0.00004498872779853021,0.00009200730710290372,0.000008351802838054331,0.00003657679432459796,0.00003311156130318219 39 | 1968,0.000038697799027431756,0.000036365540533248954,0.00004269624696462415,0.00008792540999517466,0.00001322004360796806,0.00003831603923269237,0.00003124023714917712 40 | 1969,0.000038863658119225875,0.00003425305476412177,0.00004026099971573179,0.00008772824609574552,0.000014373055819305591,0.00004465074622809576,0.000030007966415723786 41 | 1970,0.000038377950356031455,0.00003469318107818253,0.000040204782029225804,0.0000850091892061755,0.000018612748135637958,0.00004365982507200291,0.00003022440917751131 42 | 1971,0.0000394320122723002,0.00003496157538999493,0.00004069574182115806,0.00008211492483193676,0.000015242020102353612,0.00003972862032242119,0.00002936582435116482 43 | 1972,0.00003747766944191729,0.00003573653884814121,0.00004084395550307818,0.000078375349403359,0.000016425135375660222,0.00002982695999283654,0.000029427874930358183 44 | 1973,0.000037806266239689044,0.000033932767109945416,0.00004044468611634026,0.00007951013928201671,0.00001395844083162956,0.000029947373453372467,0.000028382613891153596 45 | 1974,0.00003657491955285271,0.00003307693198924729,0.000038364340677314125,0.00008230605696250375,0.000013350398755089069,0.00003539182822957324,0.00002816551265520199 46 | 1975,0.000037533568198947855,0.00003165055447122237,0.000037795317136139296,0.00008789129545524095,0.000013318622526033627,0.000036613494254803904,0.0000277604103757767 47 | 1976,0.00003801523174236839,0.00003086782877896136,0.00003750702793089052,0.00008970156341092661,0.00001272860390599817,0.00003745870587105552,0.00002732802628694723 48 | 1977,0.00003803539220825769,0.000031580599170411006,0.00003790804597277505,0.00008594682246136169,0.000012870559051710492,0.00003252082024118863,0.000028199050575494766 49 | 1978,0.000038648772412367784,0.00003109075684430233,0.000036584736032333844,0.00009055357319690908,0.000014162819752527867,0.000030261799717360798,0.00002831368025605722 50 | 1979,0.000037423525403331347,0.00003057542987032017,0.000039043216626547896,0.0000950232642935589,0.000013759557684049165,0.00003278608771021633,0.000029247951412495848 51 | 1980,0.00003673940470131735,0.00002909408734315851,0.00003929244242802573,0.00009713461865127708,0.000014563478847170094,0.000032090136907451473,0.00002813793495685483 52 | 1981,0.00003571619405799235,0.000028969137323050138,0.00003949974779970944,0.00009220923675457016,0.000011597000593610574,0.000031482527144059226,0.000027680548252343822 53 | 1982,0.00003375317464815453,0.000028352625425516937,0.000037496143098299704,0.00008874611618618171,0.000013768206069168324,0.00002660506894850793,0.00002594939057113758 54 | 1983,0.000032169156232460715,0.00002928208899296199,0.00003738201727780203,0.00009547318040858954,0.000016126355452191394,0.000028845147729346838,0.000025835857741185464 55 | 1984,0.00003427925184951164,0.00002857940974839342,0.00004031296096703348,0.00010986051590104277,0.000017250997795296524,0.000039707279332408994,0.000025236361883192632 56 | 1985,0.00003612682363988521,0.000028683313454772968,0.000041661428743585326,0.00011998663588504617,0.00001799044669799817,0.00004066844182185984,0.000025940060368156992 57 | 1986,0.0000366682773650003,0.000027222998445116293,0.00004312490394416576,0.00012154411282002305,0.000017935148207470775,0.00003811636815953534,0.00002642415347509086 58 | 1987,0.00003494436775023738,0.000026335830019282486,0.000040885797109998144,0.00011383568683716779,0.000019923846290718455,0.000028342072255327366,0.00002614776894915849 59 | 1988,0.000034383268939564005,0.000025949761644975904,0.000038596215745201334,0.0001123517601323935,0.000019829605662380345,0.0000255958996907187,0.000025573919629096054 60 | 1989,0.00003370385335680718,0.000025717805328895338,0.00003808195591166926,0.00011135047679999843,0.000017779165621808108,0.000024626750018796884,0.000024845631439044762 61 | 1990,0.000031199288666054294,0.00002614328574660855,0.00003928353786856557,0.00011181737985073899,0.000016448152261242892,0.0000215032123378478,0.000023996190066100098 62 | 1991,0.00003015123184013646,0.00002538908180819514,0.000041978556206837915,0.00012640983186429366,0.00001620080850746793,0.00002129543645423837,0.000022692514903610572 63 | 1992,0.000029958500211553957,0.000025222852248892497,0.00004119718141737394,0.00012432544948145127,0.00001647371270034152,0.000027110091347519,0.000021206548505385097 64 | 1993,0.000030331841117003933,0.000024195252990466543,0.000042906288096370794,0.00012359750932470584,0.000019743049051612616,0.00005286382778043238,0.000020281815523048863 65 | 1994,0.000029860862317339826,0.00002429047829840177,0.00004437245055063007,0.00012843463385555273,0.000021226153573176514,0.00007221442259227236,0.000020665833896297652 66 | 1995,0.000029728888572814565,0.0000241157176787965,0.00004663443057021747,0.00013461767472714806,0.0000230785026360536,0.0000766348784964066,0.000020742341803270392 67 | 1996,0.00002948489236587193,0.00002395644878561143,0.000046281311369966716,0.00013913609291194007,0.000019782985570297267,0.000055176786797043555,0.000020773984336604674 68 | 1997,0.000029381718074243206,0.00002341165418329183,0.00004475856258068234,0.00011940410816653942,0.000019221223434821393,0.000040157188777811825,0.00002006360288457169 69 | 1998,0.000029212150063055258,0.0000222770067921374,0.000041981872830850385,0.00011639744237375756,0.00001628779076175609,0.000034647520806174725,0.00002009119270951487 70 | 1999,0.000029093739916182432,0.000021677643114041228,0.00004106802953174338,0.00010661353735486045,0.000016253884799273994,0.000038616806705249473,0.000019736395188374445 71 | 2000,0.000027236030291533098,0.000021513751562451944,0.000039091883081709966,0.00010366673086537048,0.000013959502211946528,0.00004342385606529812,0.000019805942429229617 72 | 2001,0.00002643866112824374,0.00002101684064352109,0.00003882244709529914,0.00009576806769473478,0.000014167252629704308,0.00004646770321414806,0.000019178456568624824 73 | 2002,0.00002528701770643238,0.000019879904357367195,0.00003672830522797691,0.00009447979634084429,0.00001588100985827623,0.000044519267248688266,0.000019207320898810092 74 | 2003,0.00002518065957701765,0.000018043818878747214,0.00003791471681324765,0.00008901663386495784,0.000015853013489201356,0.00004275932951713912,0.000018824256888668362 75 | 2004,0.000024666767785674892,0.000017220153191980597,0.00003836413937582014,0.00008996361915099745,0.00001717287220041423,0.00004885923529703481,0.000019293038955462787 76 | 2005,0.000023089991373126395,0.00001656819040363189,0.00003779163186360771,0.00008579554075064759,0.000015569312987887923,0.000051673313767726846,0.00001928491474245675 77 | 2006,0.000021833109713043086,0.000016305872122757137,0.000035160760792981215,0.00007779661003345002,0.000018779304203538533,0.00004891184774654297,0.000019278924810350873 78 | 2007,0.00001878232311961862,0.000013727501633790476,0.00003440006184973754,0.00006850262191922714,0.000018344731264126796,0.000039758020041820906,0.000018581026476264622 79 | 2008,0.000018084586372424383,0.000012681134194281185,0.00003418100641283672,0.0000642649392830208,0.000019955369680246804,0.00003612779801187571,0.000018642283976078033 80 | -------------------------------------------------------------------------------- /2019-03-ngrams-for-all-corpora/make-ngrams.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | 4 | # take the query (or queries) from the makefile 5 | QUERY=$1 6 | 7 | # change start & end year here (2008 ist the last possible year in 2019) 8 | START_YEAR="1930" 9 | END_YEAR="2008" 10 | 11 | # change smoothing. Default = 3. 0 = not at all, 50 = a LOT. 12 | SMOOTHING="1" 13 | 14 | echo "generating ngrams for $QUERY" 15 | 16 | 17 | CORPORA= 18 | 19 | # the corpora here 20 | for CORPUS in eng_us_2012 eng_gb_2012 fre_2012 ger_2012 heb_2012 rus_2012 spa_2012 21 | do 22 | # write one csv with each corpus with the ngram.py script 23 | python ngram.py "$QUERY" -caseInsensitive -noprint -startYear=$START_YEAR -endYear=$END_YEAR -smoothing=$SMOOTHING -corpus=$CORPUS 24 | 25 | # replace the column headers in the csv, change it from query content to corpus name 26 | sed -i '' "s/$QUERY/$CORPUS/g" $CORPUS.csv 27 | #csvsql --query "select $CORPUS*1000000 AS $CORPUS-2 from '$CORPUS'" $CORPUS.csv 28 | done 29 | 30 | # use csvkit to join all the files together and put them in an own csv 31 | csvjoin -c year *_2012.csv > "all-$QUERY.csv" 32 | 33 | # delete all the individual corpora files 34 | rm *_2012.csv -------------------------------------------------------------------------------- /2019-03-ngrams-for-all-corpora/makefile: -------------------------------------------------------------------------------- 1 | ngram: 2 | @./make-ngrams.sh "1945" 3 | # @./make-ngrams.sh "2000" -------------------------------------------------------------------------------- /2019-03-ngrams-for-all-corpora/ngram.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -* 3 | from ast import literal_eval 4 | from pandas import DataFrame # http://github.com/pydata/pandas 5 | import re 6 | import requests # http://github.com/kennethreitz/requests 7 | import subprocess 8 | import sys 9 | 10 | corpora = dict(eng_us_2012=17, eng_us_2009=5, eng_gb_2012=18, eng_gb_2009=6, 11 | chi_sim_2012=23, chi_sim_2009=11, eng_2012=15, eng_2009=0, 12 | eng_fiction_2012=16, eng_fiction_2009=4, eng_1m_2009=1, 13 | fre_2012=19, fre_2009=7, ger_2012=20, ger_2009=8, heb_2012=24, 14 | heb_2009=9, spa_2012=21, spa_2009=10, rus_2012=25, rus_2009=12, 15 | ita_2012=22) 16 | 17 | 18 | def getNgrams(query, corpus, startYear, endYear, smoothing, caseInsensitive): 19 | params = dict(content=query, year_start=startYear, year_end=endYear, 20 | corpus=corpora[corpus], smoothing=smoothing, 21 | case_insensitive=caseInsensitive) 22 | if params['case_insensitive'] is False: 23 | params.pop('case_insensitive') 24 | if '?' in params['content']: 25 | params['content'] = params['content'].replace('?', '*') 26 | if '@' in params['content']: 27 | params['content'] = params['content'].replace('@', '=>') 28 | req = requests.get('http://books.google.com/ngrams/graph', params=params) 29 | res = re.findall('var data = (.*?);\\n', req.text) 30 | if res: 31 | data = {qry['ngram']: qry['timeseries'] 32 | for qry in literal_eval(res[0])} 33 | df = DataFrame(data) 34 | df.insert(0, 'year', list(range(startYear, endYear + 1))) 35 | else: 36 | df = DataFrame() 37 | return req.url, params['content'], df 38 | 39 | 40 | def runQuery(argumentString): 41 | arguments = argumentString.split() 42 | query = ' '.join([arg for arg in arguments if not arg.startswith('-')]) 43 | if '?' in query: 44 | query = query.replace('?', '*') 45 | if '@' in query: 46 | query = query.replace('@', '=>') 47 | params = [arg for arg in arguments if arg.startswith('-')] 48 | corpus, startYear, endYear, smoothing = 'eng_2012', 1800, 2008, 3 49 | printHelp, caseInsensitive, allData = False, False, False 50 | toSave, toPrint, toPlot = True, True, False 51 | 52 | # parsing the query parameters 53 | for param in params: 54 | if '-nosave' in param: 55 | toSave = False 56 | elif '-noprint' in param: 57 | toPrint = False 58 | elif '-plot' in param: 59 | toPlot = True 60 | elif '-corpus' in param: 61 | corpus = param.split('=')[1].strip() 62 | elif '-startYear' in param: 63 | startYear = int(param.split('=')[1]) 64 | elif '-endYear' in param: 65 | endYear = int(param.split('=')[1]) 66 | elif '-smoothing' in param: 67 | smoothing = int(param.split('=')[1]) 68 | elif '-caseInsensitive' in param: 69 | caseInsensitive = True 70 | elif '-alldata' in param: 71 | allData = True 72 | elif '-help' in param: 73 | printHelp = True 74 | else: 75 | print(('Did not recognize the following argument: %s' % param)) 76 | if printHelp: 77 | print('See README file.') 78 | else: 79 | if '*' in query and caseInsensitive is True: 80 | caseInsensitive = False 81 | notifyUser = True 82 | warningMessage = "*NOTE: Wildcard and case-insensitive " + \ 83 | "searches can't be combined, so the " + \ 84 | "case-insensitive option was ignored." 85 | elif '_INF' in query and caseInsensitive is True: 86 | caseInsensitive = False 87 | notifyUser = True 88 | warningMessage = "*NOTE: Inflected form and case-insensitive " + \ 89 | "searches can't be combined, so the " + \ 90 | "case-insensitive option was ignored." 91 | else: 92 | notifyUser = False 93 | url, urlquery, df = getNgrams(query, corpus, startYear, endYear, 94 | smoothing, caseInsensitive) 95 | if not allData: 96 | if caseInsensitive is True: 97 | for col in df.columns: 98 | if col.count('(All)') == 1: 99 | df[col.replace(' (All)', '')] = df.pop(col) 100 | elif col.count(':chi_') == 1 or corpus.startswith('chi_'): 101 | pass 102 | elif col.count(':ger_') == 1 or corpus.startswith('ger_'): 103 | pass 104 | elif col.count(':heb_') == 1 or corpus.startswith('heb_'): 105 | pass 106 | elif col.count('(All)') == 0 and col != 'year': 107 | if col not in urlquery.split(','): 108 | df.pop(col) 109 | if '_INF' in query: 110 | for col in df.columns: 111 | if '_INF' in col: 112 | df.pop(col) 113 | if '*' in query: 114 | for col in df.columns: 115 | if '*' in col: 116 | df.pop(col) 117 | if toPrint: 118 | print((','.join(df.columns.tolist()))) 119 | for row in df.iterrows(): 120 | try: 121 | print(('%d,' % int(row[1].values[0]) + 122 | ','.join(['%.12f' % s for s in row[1].values[1:]]))) 123 | except: 124 | print((','.join([str(s) for s in row[1].values]))) 125 | queries = ''.join(urlquery.replace(',', '_').split()) 126 | if '*' in queries: 127 | queries = queries.replace('*', 'WILDCARD') 128 | if caseInsensitive is True: 129 | word_case = 'caseInsensitive' 130 | else: 131 | word_case = 'caseSensitive' 132 | 133 | filename = '%s.csv' % (corpus, ) 134 | 135 | if toSave: 136 | for col in df.columns: 137 | if '>' in col: 138 | df[col.replace('>', '>')] = df.pop(col) 139 | df.to_csv(filename, index=False) 140 | print(('Data saved to %s' % filename)) 141 | if toPlot: 142 | try: 143 | subprocess.call(['python', 'xkcd.py', filename]) 144 | except: 145 | if not toSave: 146 | print(('Currently, if you want to create a plot you ' + 147 | 'must also save the data. Rerun your query, ' + 148 | 'removing the -nosave option.')) 149 | else: 150 | print(('Plotting Failed: %s' % filename)) 151 | if notifyUser: 152 | print(warningMessage) 153 | 154 | if __name__ == '__main__': 155 | argumentString = ' '.join(sys.argv[1:]) 156 | if argumentString == '': 157 | argumentString = eval(input('Enter query (or -help):')) 158 | else: 159 | try: 160 | runQuery(argumentString) 161 | except: 162 | print('An error occurred.') 163 | 164 | -------------------------------------------------------------------------------- /2019-06-greenland-ice-melting/README.md: -------------------------------------------------------------------------------- 1 | 2 | # Greenland’s surface melt extent 3 | 4 | All readings of Greenland’s surface melt extent in square kilometre, between April 1st, 1979 and June 18th, 2019, as collected by the National Snow and Ice Data Center. 5 | 6 | Taken from this Highcharts chart: [https://nsidc.org/greenland-today/greenland-surface-melt-extent-interactive-chart/](https://nsidc.org/greenland-today/greenland-surface-melt-extent-interactive-chart/). 7 | 8 | Run the script in R to get the newest data! 9 | 10 | -------------------------------------------------------------------------------- /2019-06-greenland-ice-melting/script.R: -------------------------------------------------------------------------------- 1 | needs(rjson, dplyr) 2 | 3 | years = seq(1979, 2019) 4 | out = data_frame(days=seq(91,304)) 5 | 6 | for (year in years) { 7 | print(year) 8 | d1 <- fromJSON(readLines(paste0('https://nsidc.org/api/greenland/melt_area/', year))) 9 | d2 <- data_frame(time=as.Date(names(unlist(d1))), x=unlist(d1)) %>% 10 | rename_at(c('x'), function(x) { year }) %>% 11 | mutate(days=as.numeric(time - as.Date(paste0(year,'-01-01'))+1)) %>% 12 | select(-time) 13 | out <- out %>% left_join(d2, by = 'days') 14 | } 15 | 16 | write.csv(out, "greenland-ice.csv") 17 | 18 | -------------------------------------------------------------------------------- /2019-11-api-updates/Readme.md: -------------------------------------------------------------------------------- 1 | # Automatic Updates for Live Data 2 | 3 | This script is using the Alpha Vantage and Datawrapper API to update charts with new data and republish them. 4 | A guide can be found here: https://developer.datawrapper.de/docs/automatic-updates-for-live-data. 5 | 6 | To run the script you need Node.js and `got` from npm. 7 | 8 | Before the first run replace the following values: 9 | 10 | * `API_KEY` - This is your Alpha Vantage API key. You can create a free one here https://www.alphavantage.co/support/#api-key. 11 | * `CHART_ID` - The ID of the chart you want to update. 12 | * `DW_TOKEN` - Your Datawrapper API Token. Check out how to create one here: https://developer.datawrapper.de/docs/getting-started#section-authentication 13 | 14 | If you replaced these values you can run `node script.js`. 15 | -------------------------------------------------------------------------------- /2019-11-api-updates/deno.script.js: -------------------------------------------------------------------------------- 1 | import { dotenv } from './lib/dotenv.js' 2 | dotenv() 3 | 4 | const API_KEY = Deno.env('API_KEY') 5 | const CHART_ID = Deno.env('CHART_ID') 6 | const DW_TOKEN = Deno.env('DW_TOKEN') 7 | 8 | const FAANG = ["FB", "AMZN", "AAPL", "NFLX", "GOOG"]; 9 | 10 | async function main() { 11 | /* Function that loads CSV stock data from external data source */ 12 | const stocks = await getStockData(); 13 | 14 | console.log(`[${CHART_ID}] Fetched new data.`); 15 | 16 | await request( 17 | `https://api.datawrapper.de/v3/charts/${CHART_ID}/data`, 18 | { 19 | method: "PUT", 20 | headers: { 21 | "content-type": "text/csv" 22 | }, 23 | body: stocks 24 | } 25 | ); 26 | 27 | console.log(`[${CHART_ID}] Data updated.`); 28 | 29 | /* Update chart note with current date to reflect the change */ 30 | await request( 31 | `https://api.datawrapper.de/v3/charts/${CHART_ID}`, 32 | { 33 | method: "PATCH", 34 | json: true, 35 | body: { 36 | metadata: { 37 | annotate: { 38 | notes: `Last update: ${new Date().toLocaleString()}` 39 | } 40 | } 41 | } 42 | } 43 | ); 44 | 45 | console.log(`[${CHART_ID}] Last update time updated.`); 46 | 47 | /* Republish the chart to make the new data available */ 48 | const publishResponse = await request( 49 | `https://api.datawrapper.de/charts/${CHART_ID}/publish`, 50 | { 51 | json: true, 52 | method: "POST" 53 | } 54 | ); 55 | 56 | console.log(`[${CHART_ID}] Chart published. 57 | 58 | https:${publishResponse.data.publicUrl}`); 59 | } 60 | 61 | main(); 62 | 63 | function api(stock) { 64 | const query = new URLSearchParams([ 65 | ["apikey", API_KEY], 66 | ["function", "TIME_SERIES_DAILY"], 67 | ["symbol", stock], 68 | ["interval", "1min"], 69 | ["datatype", "json"] 70 | ]); 71 | 72 | return request(`https://www.alphavantage.co/query?${query.toString()}`, { 73 | headers: { "content-type": "application/json" }, 74 | json: true 75 | }); 76 | } 77 | 78 | async function getStockData() { 79 | const responses = await Promise.all(FAANG.map(stock => api(stock))); 80 | 81 | let data = responses.map((d, i) => 82 | Object.entries(d["Time Series (Daily)"]).map(e => ({ 83 | date: e[0], 84 | val: e[1]["4. close"], 85 | [e[0]]: e[1]["4. close"], 86 | stock: FAANG[i] 87 | }) 88 | ) 89 | ); 90 | 91 | const dates = data[0].map(d => d.date); 92 | 93 | data = data.map(d => 94 | d.reduce((coll, s) => { 95 | coll[s.date] = s; 96 | return coll; 97 | }, {}) 98 | ); 99 | 100 | data = dates.reduce( 101 | (coll, date) => { 102 | coll.push( 103 | [date, ...data.map(d => (d[date] ? d[date].val : undefined))].join("|") 104 | ); 105 | 106 | return coll; 107 | }, 108 | [["Date", FAANG.join("|")].join("|")] 109 | ); 110 | 111 | return data.join("\n"); 112 | } 113 | 114 | async function request( 115 | url, 116 | { json, headers, body, ...options } = { headers: {} } 117 | ) { 118 | const response = await fetch(url, { 119 | headers: { 120 | authorization: `Bearer ${DW_TOKEN}`, 121 | ...headers, 122 | "content-type": json ? "application/json" : headers["content-type"] 123 | }, 124 | body: json ? JSON.stringify(body) : body, 125 | ...options 126 | }); 127 | 128 | if (json) return response.json(); 129 | return response; 130 | } 131 | -------------------------------------------------------------------------------- /2019-11-api-updates/lib/dotenv.js: -------------------------------------------------------------------------------- 1 | export function dotenv () { 2 | const env = Deno.env() 3 | const decoder = new TextDecoder('utf-8') 4 | let data = Deno.readFileSync('.env') 5 | data = decoder 6 | .decode(data) 7 | .trim() 8 | .split('\n') 9 | .map(line => line.split('=')) 10 | .forEach(([key, value]) => { env[key.trim()] = value.trim() }) 11 | } 12 | 13 | -------------------------------------------------------------------------------- /2019-11-api-updates/script.js: -------------------------------------------------------------------------------- 1 | const got = require('got') 2 | 3 | const API_KEY = '' // https://www.alphavantage.co/ 4 | const FAANG = ['FB', 'AMZN', 'AAPL', 'NFLX', 'GOOG'] 5 | const CHART_ID = '' // Chart you want to update 6 | const DW_TOKEN = '' // Datawrapper API token 7 | 8 | async function main() { 9 | /* Function that loads CSV stock data from external data source */ 10 | const stocks = await getStockData() 11 | 12 | console.log(`[${CHART_ID}] Fetched new data.`) 13 | 14 | 15 | const dataResponse = await request( 16 | `https://api.datawrapper.de/v3/charts/${CHART_ID}/data`, 17 | { 18 | method: 'PUT', 19 | body: stocks 20 | } 21 | ) 22 | 23 | console.log(`[${CHART_ID}] Data updated.`) 24 | 25 | /* Update chart note with current date to reflect the change */ 26 | const chartResponse = await request( 27 | `https://api.datawrapper.de/v3/charts/${CHART_ID}`, 28 | { 29 | method: 'PATCH', 30 | json: true, 31 | body: { 32 | metadata: { 33 | annotate: { 34 | notes: `Last update: ${new Date().toLocaleString()}` 35 | } 36 | } 37 | } 38 | } 39 | ) 40 | 41 | console.log(`[${CHART_ID}] Last update time updated.`) 42 | 43 | /* Republish the chart to make the new data available */ 44 | const publishResponse = await request( 45 | `https://api.datawrapper.de/charts/${CHART_ID}/publish`, 46 | { 47 | json: true, 48 | method: 'POST' 49 | } 50 | ) 51 | 52 | console.log(`[${CHART_ID}] Chart published. 53 | 54 | https:${publishResponse.body.data.publicUrl}`) 55 | } 56 | 57 | main() 58 | 59 | function api(stock) { 60 | return got('/', { 61 | json: true, 62 | baseUrl: 'https://www.alphavantage.co/query', 63 | query: new URLSearchParams([ 64 | ['apikey', API_KEY], 65 | ['function', 'TIME_SERIES_DAILY'], 66 | ['symbol', stock], 67 | ['interval', '1min'], 68 | ['datatype', 'json'] 69 | ]) 70 | }) 71 | } 72 | 73 | async function getStockData() { 74 | const responses = await Promise.all(FAANG.map(stock => api(stock))) 75 | let data = responses.map(res => res.body) 76 | 77 | data = data.map((d, i) => 78 | Object.entries(d['Time Series (Daily)']).map(e => ({ 79 | date: e[0], 80 | val: e[1]['4. close'], 81 | [e[0]]: e[1]['4. close'], 82 | stock: FAANG[i] 83 | })) 84 | ) 85 | 86 | const dates = data[0].map(d => d.date) 87 | 88 | data = data.map(d => 89 | d.reduce((coll, s) => { 90 | coll[s.date] = s 91 | return coll 92 | }, {}) 93 | ) 94 | 95 | data = dates.reduce( 96 | (coll, date) => { 97 | coll.push( 98 | [date, ...data.map(d => (d[date] ? d[date].val : undefined))].join('|') 99 | ) 100 | 101 | return coll 102 | }, 103 | [['Date', FAANG.join('|')].join('|')] 104 | ) 105 | 106 | return data.join('\n') 107 | } 108 | 109 | function request(url, options) { 110 | return got(url, { 111 | headers: { 112 | authorization: `Bearer ${DW_TOKEN}` 113 | }, 114 | ...options 115 | }) 116 | } 117 | -------------------------------------------------------------------------------- /2020-02-06-temperature-chart/january-temp-range.csv: -------------------------------------------------------------------------------- 1 | date,range,daily.mean,base.high,base.low,record.high,record.low 2 | 2020-01-01T00:00:00Z,NA,NA,2.56,-2.27,12.2,-19.3 3 | 2020-01-01T12:00:00Z,-3.5,1.7,2.56,-2.27,12.2,-19.3 4 | 2020-01-01T12:00:00Z,4.8,NA,2.56,-2.27,12.2,-19.3 5 | 2020-01-01T23:59:59Z,NA,NA,2.56,-2.27,12.2,-19.3 6 | 2020-01-02T00:00:00Z,NA,NA,2.91,-1.99,12.9,-21.4 7 | 2020-01-02T12:00:00Z,-4.3,0.5,2.91,-1.99,12.9,-21.4 8 | 2020-01-02T12:00:00Z,6.9,NA,2.91,-1.99,12.9,-21.4 9 | 2020-01-02T23:59:59Z,NA,NA,2.91,-1.99,12.9,-21.4 10 | 2020-01-03T00:00:00Z,NA,NA,3.22,-1.86,12.7,-18.3 11 | 2020-01-03T12:00:00Z,1.1,4.5,3.22,-1.86,12.7,-18.3 12 | 2020-01-03T12:00:00Z,7,NA,3.22,-1.86,12.7,-18.3 13 | 2020-01-03T23:59:59Z,NA,NA,3.22,-1.86,12.7,-18.3 14 | 2020-01-04T00:00:00Z,NA,NA,2.84,-1.63,11.6,-18.8 15 | 2020-01-04T12:00:00Z,1.3,3.9,2.84,-1.63,11.6,-18.8 16 | 2020-01-04T12:00:00Z,5.6,NA,2.84,-1.63,11.6,-18.8 17 | 2020-01-04T23:59:59Z,NA,NA,2.84,-1.63,11.6,-18.8 18 | 2020-01-05T00:00:00Z,NA,NA,2.99,-2.19,14.2,-16.1 19 | 2020-01-05T12:00:00Z,-2.8,1.2,2.99,-2.19,14.2,-16.1 20 | 2020-01-05T12:00:00Z,3.9,NA,2.99,-2.19,14.2,-16.1 21 | 2020-01-05T23:59:59Z,NA,NA,2.99,-2.19,14.2,-16.1 22 | 2020-01-06T00:00:00Z,NA,NA,3.56,-1.57,14.6,-16.6 23 | 2020-01-06T12:00:00Z,2.4,4.9,3.56,-1.57,14.6,-16.6 24 | 2020-01-06T12:00:00Z,6.9,NA,3.56,-1.57,14.6,-16.6 25 | 2020-01-06T23:59:59Z,NA,NA,3.56,-1.57,14.6,-16.6 26 | 2020-01-07T00:00:00Z,NA,NA,2.85,-2.47,11.5,-19.7 27 | 2020-01-07T12:00:00Z,-2.2,2.6,2.85,-2.47,11.5,-19.7 28 | 2020-01-07T12:00:00Z,5.7,NA,2.85,-2.47,11.5,-19.7 29 | 2020-01-07T23:59:59Z,NA,NA,2.85,-2.47,11.5,-19.7 30 | 2020-01-08T00:00:00Z,NA,NA,2.65,-2.91,12.5,-17.3 31 | 2020-01-08T12:00:00Z,3.2,6.4,2.65,-2.91,12.5,-17.3 32 | 2020-01-08T12:00:00Z,8.8,NA,2.65,-2.91,12.5,-17.3 33 | 2020-01-08T23:59:59Z,NA,NA,2.65,-2.91,12.5,-17.3 34 | 2020-01-09T00:00:00Z,NA,NA,2.85,-2.3,14.1,-17.4 35 | 2020-01-09T12:00:00Z,7.4,8.5,2.85,-2.3,14.1,-17.4 36 | 2020-01-09T12:00:00Z,10,NA,2.85,-2.3,14.1,-17.4 37 | 2020-01-09T23:59:59Z,NA,NA,2.85,-2.3,14.1,-17.4 38 | 2020-01-10T00:00:00Z,NA,NA,3.13,-1.45,15.1,-19.2 39 | 2020-01-10T12:00:00Z,4.2,9.2,3.13,-1.45,15.1,-19.2 40 | 2020-01-10T12:00:00Z,11.2,NA,3.13,-1.45,15.1,-19.2 41 | 2020-01-10T23:59:59Z,NA,NA,3.13,-1.45,15.1,-19.2 42 | 2020-01-11T00:00:00Z,NA,NA,2.71,-2.46,11.6,-21 43 | 2020-01-11T12:00:00Z,2.2,4.4,2.71,-2.46,11.6,-21 44 | 2020-01-11T12:00:00Z,6.8,NA,2.71,-2.46,11.6,-21 45 | 2020-01-11T23:59:59Z,NA,NA,2.71,-2.46,11.6,-21 46 | 2020-01-12T00:00:00Z,NA,NA,3.27,-1.62,10.5,-19.2 47 | 2020-01-12T12:00:00Z,0.8,3.7,3.27,-1.62,10.5,-19.2 48 | 2020-01-12T12:00:00Z,6.8,NA,3.27,-1.62,10.5,-19.2 49 | 2020-01-12T23:59:59Z,NA,NA,3.27,-1.62,10.5,-19.2 50 | 2020-01-13T00:00:00Z,NA,NA,2.61,-2.27,12.5,-18.6 51 | 2020-01-13T12:00:00Z,2.6,5.7,2.61,-2.27,12.5,-18.6 52 | 2020-01-13T12:00:00Z,7.8,NA,2.61,-2.27,12.5,-18.6 53 | 2020-01-13T23:59:59Z,NA,NA,2.61,-2.27,12.5,-18.6 54 | 2020-01-14T00:00:00Z,NA,NA,3.39,-2.09,13.6,-20.1 55 | 2020-01-14T12:00:00Z,2.9,7.4,3.39,-2.09,13.6,-20.1 56 | 2020-01-14T12:00:00Z,10.5,NA,3.39,-2.09,13.6,-20.1 57 | 2020-01-14T23:59:59Z,NA,NA,3.39,-2.09,13.6,-20.1 58 | 2020-01-15T00:00:00Z,NA,NA,3.05,-1.56,11,-17.5 59 | 2020-01-15T12:00:00Z,8.1,10.5,3.05,-1.56,11,-17.5 60 | 2020-01-15T12:00:00Z,13.7,NA,3.05,-1.56,11,-17.5 61 | 2020-01-15T23:59:59Z,NA,NA,3.05,-1.56,11,-17.5 62 | 2020-01-16T00:00:00Z,NA,NA,3.75,-0.91,12.9,-15.4 63 | 2020-01-16T12:00:00Z,2.5,7.2,3.75,-0.91,12.9,-15.4 64 | 2020-01-16T12:00:00Z,10.4,NA,3.75,-0.91,12.9,-15.4 65 | 2020-01-16T23:59:59Z,NA,NA,3.75,-0.91,12.9,-15.4 66 | 2020-01-17T00:00:00Z,NA,NA,3.86,-1.65,13.9,-15.8 67 | 2020-01-17T12:00:00Z,1.9,5.1,3.86,-1.65,13.9,-15.8 68 | 2020-01-17T12:00:00Z,9,NA,3.86,-1.65,13.9,-15.8 69 | 2020-01-17T23:59:59Z,NA,NA,3.86,-1.65,13.9,-15.8 70 | 2020-01-18T00:00:00Z,NA,NA,3.66,-1.71,13.3,-14.4 71 | 2020-01-18T12:00:00Z,2.1,5.3,3.66,-1.71,13.3,-14.4 72 | 2020-01-18T12:00:00Z,7.2,NA,3.66,-1.71,13.3,-14.4 73 | 2020-01-18T23:59:59Z,NA,NA,3.66,-1.71,13.3,-14.4 74 | 2020-01-19T00:00:00Z,NA,NA,3.52,-1.06,11.6,-19.4 75 | 2020-01-19T12:00:00Z,2.6,3.7,3.52,-1.06,11.6,-19.4 76 | 2020-01-19T12:00:00Z,5.1,NA,3.52,-1.06,11.6,-19.4 77 | 2020-01-19T23:59:59Z,NA,NA,3.52,-1.06,11.6,-19.4 78 | 2020-01-20T00:00:00Z,NA,NA,3.77,-1.81,13.8,-19.9 79 | 2020-01-20T12:00:00Z,-2.1,1.1,3.77,-1.81,13.8,-19.9 80 | 2020-01-20T12:00:00Z,4.5,NA,3.77,-1.81,13.8,-19.9 81 | 2020-01-20T23:59:59Z,NA,NA,3.77,-1.81,13.8,-19.9 82 | 2020-01-21T00:00:00Z,NA,NA,3.63,-1.78,10.9,-18 83 | 2020-01-21T12:00:00Z,-0.7,2.1,3.63,-1.78,10.9,-18 84 | 2020-01-21T12:00:00Z,5.7,NA,3.63,-1.78,10.9,-18 85 | 2020-01-21T23:59:59Z,NA,NA,3.63,-1.78,10.9,-18 86 | 2020-01-22T00:00:00Z,NA,NA,3.63,-1.87,13.8,-16.2 87 | 2020-01-22T12:00:00Z,0,4,3.63,-1.87,13.8,-16.2 88 | 2020-01-22T12:00:00Z,6.3,NA,3.63,-1.87,13.8,-16.2 89 | 2020-01-22T23:59:59Z,NA,NA,3.63,-1.87,13.8,-16.2 90 | 2020-01-23T00:00:00Z,NA,NA,3.22,-1.54,11.4,-16.7 91 | 2020-01-23T12:00:00Z,-1.9,2.8,3.22,-1.54,11.4,-16.7 92 | 2020-01-23T12:00:00Z,6,NA,3.22,-1.54,11.4,-16.7 93 | 2020-01-23T23:59:59Z,NA,NA,3.22,-1.54,11.4,-16.7 94 | 2020-01-24T00:00:00Z,NA,NA,3.22,-1.18,11.9,-16.4 95 | 2020-01-24T12:00:00Z,-2.7,0,3.22,-1.18,11.9,-16.4 96 | 2020-01-24T12:00:00Z,3.7,NA,3.22,-1.18,11.9,-16.4 97 | 2020-01-24T23:59:59Z,NA,NA,3.22,-1.18,11.9,-16.4 98 | 2020-01-25T00:00:00Z,NA,NA,3.12,-1.77,12.1,-13.9 99 | 2020-01-25T12:00:00Z,-0.1,0.8,3.12,-1.77,12.1,-13.9 100 | 2020-01-25T12:00:00Z,1.9,NA,3.12,-1.77,12.1,-13.9 101 | 2020-01-25T23:59:59Z,NA,NA,3.12,-1.77,12.1,-13.9 102 | 2020-01-26T00:00:00Z,NA,NA,3.76,-1.85,13,-17.6 103 | 2020-01-26T12:00:00Z,-1.7,-0.3,3.76,-1.85,13,-17.6 104 | 2020-01-26T12:00:00Z,1.1,NA,3.76,-1.85,13,-17.6 105 | 2020-01-26T23:59:59Z,NA,NA,3.76,-1.85,13,-17.6 106 | 2020-01-27T00:00:00Z,NA,NA,3.41,-1.95,13.8,-18.3 107 | 2020-01-27T12:00:00Z,0.5,5.3,3.41,-1.95,13.8,-18.3 108 | 2020-01-27T12:00:00Z,9.3,NA,3.41,-1.95,13.8,-18.3 109 | 2020-01-27T23:59:59Z,NA,NA,3.41,-1.95,13.8,-18.3 110 | 2020-01-28T00:00:00Z,NA,NA,3.48,-2.33,14.9,-13.4 111 | 2020-01-28T12:00:00Z,2.3,5.8,3.48,-2.33,14.9,-13.4 112 | 2020-01-28T12:00:00Z,8.9,NA,3.48,-2.33,14.9,-13.4 113 | 2020-01-28T23:59:59Z,NA,NA,3.48,-2.33,14.9,-13.4 114 | 2020-01-29T00:00:00Z,NA,NA,3.3,-1.32,11.6,-12.3 115 | 2020-01-29T12:00:00Z,3.1,4.6,3.3,-1.32,11.6,-12.3 116 | 2020-01-29T12:00:00Z,6.9,NA,3.3,-1.32,11.6,-12.3 117 | 2020-01-29T23:59:59Z,NA,NA,3.3,-1.32,11.6,-12.3 118 | 2020-01-30T00:00:00Z,NA,NA,3.9,-0.94,12.5,-16.5 119 | 2020-01-30T12:00:00Z,2.2,5.7,3.9,-0.94,12.5,-16.5 120 | 2020-01-30T12:00:00Z,8.3,NA,3.9,-0.94,12.5,-16.5 121 | 2020-01-30T23:59:59Z,NA,NA,3.9,-0.94,12.5,-16.5 122 | 2020-01-31T00:00:00Z,NA,NA,4.02,-1.14,12.3,-24.4 123 | 2020-01-31T12:00:00Z,6.2,9.7,4.02,-1.14,12.3,-24.4 124 | 2020-01-31T12:00:00Z,11.2,NA,4.02,-1.14,12.3,-24.4 125 | 2020-01-31T23:59:59Z,NA,NA,4.02,-1.14,12.3,-24.4 126 | 2020-02-01T00:00:00Z,NA,NA,4.33,-1.65,11.8,-17.7 127 | 2020-02-01T12:00:00Z,7.1,10.9,4.33,-1.65,11.8,-17.7 128 | 2020-02-01T12:00:00Z,12.6,NA,4.33,-1.65,11.8,-17.7 129 | 2020-02-01T23:59:59Z,NA,NA,4.33,-1.65,11.8,-17.7 130 | 2020-02-02T00:00:00Z,NA,NA,4.25,-1.5,16.8,-19.2 131 | 2020-02-02T12:00:00Z,5.2,6.9,4.25,-1.5,16.8,-19.2 132 | 2020-02-02T12:00:00Z,8.7,NA,4.25,-1.5,16.8,-19.2 133 | 2020-02-02T23:59:59Z,NA,NA,4.25,-1.5,16.8,-19.2 134 | 2020-02-03T00:00:00Z,NA,NA,3.91,-1.06,16,-17.2 135 | 2020-02-03T12:00:00Z,5,7,3.91,-1.06,16,-17.2 136 | 2020-02-03T12:00:00Z,9.8,NA,3.91,-1.06,16,-17.2 137 | 2020-02-03T23:59:59Z,NA,NA,3.91,-1.06,16,-17.2 138 | 2020-02-04T00:00:00Z,NA,NA,4.45,-1.21,14.3,-17.2 139 | 2020-02-04T12:00:00Z,3.3,5,4.45,-1.21,14.3,-17.2 140 | 2020-02-04T12:00:00Z,6.5,NA,4.45,-1.21,14.3,-17.2 141 | 2020-02-04T23:59:59Z,NA,NA,4.45,-1.21,14.3,-17.2 142 | 2020-02-05T00:00:00Z,NA,NA,4.85,-0.81,15.5,-18 143 | 2020-02-05T12:00:00Z,1,3,4.85,-0.81,15.5,-18 144 | 2020-02-05T12:00:00Z,5.4,NA,4.85,-0.81,15.5,-18 145 | 2020-02-05T23:59:59Z,NA,NA,4.85,-0.81,15.5,-18 146 | -------------------------------------------------------------------------------- /2020-02-06-temperature-chart/plot.R: -------------------------------------------------------------------------------- 1 | needs(tidyverse, lubridate) 2 | 3 | d <- read_csv('https://vis4.net/data/dwd/stations/00430.csv?x') %>% 4 | mutate(day=format(date, '-%m-%d')) 5 | 6 | normalMin <- 1980 7 | normalMax <- normalMin + 30 8 | 9 | contextDay <- d %>% 10 | filter(year(date) >= normalMin & year(date) < normalMax) %>% 11 | mutate(date = as.Date(paste0('2020-', format(date, '%m-%d')))) %>% 12 | group_by(date) %>% 13 | summarise(TMK.base=mean(TMK), 14 | TNK.base=round(mean(TNK),2), 15 | TXK.base=round(mean(TXK),2)) %>% 16 | mutate(day=format(date, '-%m-%d')) %>% 17 | select(-date) 18 | 19 | record <- d %>% 20 | filter(year(date) < 2020) %>% 21 | mutate(date = as.Date(paste0('2020-', format(date, '%m-%d')))) %>% 22 | group_by(date) %>% 23 | summarise(TNK.min=min(TNK), TXK.max=max(TXK)) %>% 24 | mutate(day=format(date, '-%m-%d')) %>% 25 | select(-date) 26 | 27 | january <- d %>% 28 | filter(date > as.Date('2019-12-31')) %>% 29 | left_join(contextDay, 'day') %>% 30 | left_join(record, 'day') 31 | 32 | 33 | range.low <- january %>% 34 | select(date, range=TNK, 35 | daily.mean=TMK, 36 | base.high=TXK.base, 37 | base.low=TNK.base, 38 | record.high=TXK.max, record.low=TNK.min) %>% 39 | mutate(date=as_datetime(paste0(date, '12:00:00'))) 40 | 41 | range.high <- january %>% 42 | select(date, range=TXK, 43 | base.high=TXK.base, base.low=TNK.base, 44 | record.high=TXK.max, record.low=TNK.min) %>% 45 | mutate(date=as_datetime(paste0(date, '12:00:00'))) 46 | 47 | day.start <- january %>% 48 | select(date, 49 | base.high=TXK.base, base.low=TNK.base, 50 | record.high=TXK.max, record.low=TNK.min) %>% 51 | mutate(date=as_datetime(paste0(date, '00:00:00')), 52 | range=NA) 53 | 54 | day.end <- january %>% 55 | select(date, base.high=TXK.base, base.low=TNK.base, 56 | record.high=TXK.max, record.low=TNK.min) %>% 57 | mutate(date=as_datetime(paste0(date, '23:59:59')), 58 | range=NA) 59 | 60 | all <- bind_rows(range.low, 61 | range.high, 62 | day.start, 63 | day.end) %>% 64 | arrange(date) # we need to sort by date to fix order 65 | 66 | all %>% 67 | write_csv('january-temp-range.csv') 68 | 69 | -------------------------------------------------------------------------------- /2020-03-coronavirus-charts/README.md: -------------------------------------------------------------------------------- 1 | # Edits 2 | 3 | Here you can find our latest changes to the charts, maps, and tables in the Datawrapper article ["17 (or so) responsible live visualizations about the coronavirus, for you to use"](https://blog.datawrapper.de/coronaviruscharts/). (We don't mention when we fix obvious bugs that appear because the data source changes e.g. how it formats data.) 4 | 5 | The R script might always not up to date; we'll push it every few days to this repo. 6 | 7 | #### October 5 8 | The coronavirus, sadly, is back in our news feeds: In many Western countries, cases are on the rise. We made some changes to our article so that we keep offering useful visualizations: 9 | - moved the excess mortality charts to the bottom of the article. 10 | - removed many visualizations from the article, including the car/public transport routing charts, lots of maps that show the number of tota cases per county/state/etc. You can still find all these charts and maps in the River; they're linked at the bottom of the article. They're also getting updated as frequently as before (every 20min). 11 | 12 | 13 | #### June 9 14 | - Moved all visualizations above our thoughts on responsible data visualizations. 15 | - Changed the order of visualizations at the top. 16 | - Removed some visualizations from the article (all on doubling rates, for example). You can still find them linked in the index below the visusalizations. 17 | - Added line charts for Brazil, Pakistan, Iran, India, Russia, Peru. 18 | - Added small multiple line charts with weekly mortality for selected countries and cities. 19 | - Added a table comparing new cases last week with new cases the week before. 20 | 21 | #### April 15 22 | - Added a chart showing per capita cases in US counties and states. 23 | - Added a chart showing the change in requests for car directions on Apple Maps. 24 | - Added a chart showing the change in requests for public transport directions on Apple Maps. 25 | - Removed numbers after the decimal point for all tables showing doubling days. These days are calculated based on uncertain numbers and can only show a trend, not hard facts. 26 | - Added bar charts in the table "Coronavirus COVID-19 cases in all countries" 27 | 28 | #### April 10 29 | - Put a seven day rolling average on both doubling time line charts (for confirmed cases and deaths). 30 | - Round the number of confirmed cases, deaths and recoveries to give them an approximate rather than a fact-like feel. 31 | - Highlighted Turkey in the chart "Growth rate of confirmed cases in selected countries", and removed the highlight of Isreal. 32 | 33 | 34 | #### April 9 35 | - Brought back the area chart showing confirmed cases per day in selected countries and regions. 36 | - Put a **seven day rolling average** on both area charts showing confirmed cases and deaths per day in selected countries and regions. 37 | - Put a seven day rolling average on all line charts showing new cases, deaths and recoveries per day 38 | 39 | #### April 7 40 | - Added a map of confirmed cases in US counties, colored by per capita numbers. 41 | 42 | #### April 1 43 | - Brought back the number of recovered cases to every chart and table possible. 44 | - Added a table with the growth rates of confirmed cases in US **counties**. 45 | 46 | #### March 28 47 | - Added a line chart of the growth rate of deaths. 48 | - Did some housecleaning, so that the article doesn't load too long: 49 | - Removed the chart showing doubling times of confirmed _cases_ and the chart showing growth rates on confirmed _cases_, but linked to them in case readers are still interested. They still get updated every day. 50 | - Removed the map of confirmed cases in Chinese regions, because it doesn't add much new information anymore. It still gets updated and you can find it [here](https://www.datawrapper.de/_/5ASge/) and [in the River](https://river.datawrapper.de/_/5ASge) if you want to re-use it. 51 | - Replaced the US county map with an US state map. You can still find the US county map [here](https://www.datawrapper.de/_/WmR3P/) and [in the River](https://river.datawrapper.de/_/WmR3P). 52 | 53 | #### March 25 54 | - Updated all maps & map tooltips to only show confirmed cases and deaths, not recoveries anymore. 55 | 56 | #### March 24 57 | - Changed the area chart "New confirmed COVID–19 cases, per day" to an area chart "New confirmed COVID–19 _deaths_, per day". 58 | 59 | #### March 24 60 | 61 | - Today is a sad day: Johns Hopkins university [decided](https://github.com/CSSEGISandData/COVID-19/issues/1250) to **not track recovered cases anymore**, so we removed them from all our visualizations. (You can still find the historical number of recoveries [here](https://github.com/CSSEGISandData/COVID-19/blob/master/csse_covid_19_data/csse_covid_19_time_series/time_series_19-covid-Recovered.csv).) Many countries (e.g. Germany) haven't properly reported recovered cases, so these numbers were likely too low anyway. But now our visualizations look like there are no recoveries at all – so we added bold text over some of them stating that lots of people recovered already. The following three changes were made due to the change in the Johns Hopkins data: 62 | - Changed the stacked bar charts to split bar charts. 63 | - Removed the area chart showing current cases, deaths and recoveries worldwide, since it's too similar to the line chart now. 64 | - Removed the table "Current cases, recoveries and deaths in selected countries", since it's now too similar to the sorted table "Current cases, recoveries and deaths in all countries" 65 | 66 | - In addition: Added the line chart "Growth rate of confirmed cases in selected countries" 67 | - Added the area chart "New confirmed COVID–19 cases, per day" 68 | - Added a chart showing doubling times of _deaths_. 69 | 70 | 71 | #### March 23 72 | 73 | - Replaced table at the top with the table from [the last Weekly Chart](/weekly-chart-coronavirus-doublingtimes/) because it gives a more nuanced view on doubling times and new confirmed cases. 74 | - Deleted the two outdated maps from Germany. You can still find them here: symbol map of individual confirmed cases](https://www.datawrapper.de/_/iSPw2/) / [confirmed cases in Berlin](https://www.datawrapper.de/_/E23mz/). 75 | - We now show US cases on the county level, not the state level. 76 | - The line chart showing doubling rates at the top of this article now includes more countries and updates automatically. 77 | 78 | #### March 20 79 | 80 | - Added a stacked bar chart of the number of confirmed cases, deaths & recoveries by continent 81 | 82 | #### March 18 83 | 84 | - Moved the most interesting charts and tables to the top, so that it's easier to see them when loading the page. 85 | - Added a column chart showing confirmed current cases, recoveries and deaths over time for **Spain**. 86 | - Added a table showing doubling times of cases. 87 | - Changed the title from "17 responsible live visualizations about the coronavirus, for you to use" to "17 (or so) responsible live visualizations about the coronavirus, for you to use". 88 | 89 | 90 | #### March 16 91 | 92 | - Changed the charts showing cases over time in Europe, Italy and Germany back from WHO data to Johns Hopkins data with an annotation & note that the March 12 and March 13 data is unreliable. Added the same annotation for the area and line chart showing cases worldwide. Unfortunately, Johns Hopkins still didn't change the incorrect data for the two dates, but they've added reliable-looking data since then; and they're still one of the few sources showing recovered cases. Now that the charts themselves point out the wrong data, we removed the disclaimers in the article. 93 | 94 | #### March 15 95 | 96 | - Changed the stacked bar chart to show countries with more than 300 cases instead of countries with more than 50 cases. (The stacked bar chart had become too long.) 97 | - Added Spain to the table "Coronavirus COVID-19 cases in selected countries" 98 | 99 | #### March 14 100 | 101 | - Added a disclaimer at the top of the article: "Johns Hopkins university, the source of almost all of the charts, maps and tables below, is [currently experiencing technical issues](https://github.com/CSSEGISandData/COVID-19/issues/650). **The visualizations that show cases in the US, in China and worldwide over time are therefore incorrect.** If you're using them in your articles, please inform your readers about the issue. The charts that show cases in Europe, Italy and Germany over time now use [WHO data](https://experience.arcgis.com/experience/685d0ace521648f8a5beeeee1b9125cd)." 102 | - Changed the source from Johns Hopkins data to WHO data for charts showing cases over time in Europe, Italy and Germany. Unfortunately, the WHO data doesn't give us the number of recovered people. We will switch back to Johns Hopkins data as soon as they resolved their technical issues. 103 | - Added a disclaimer that the maps with individual cases in Germany are not updated anymore. 104 | 105 | #### March 13 106 | 107 | - Included the Czech Republic to the symbol map of Europe (finally). 108 | - Brought back the column chart of Chinese cases, deaths & recoveries over time. 109 | - The Johns Hopkins University [didn't properly update](https://github.com/CSSEGISandData/COVID-19/issues/619) the numbers for **73 countries** for March 12. Our maps and charts heavily rely on them, since we don't have the capacity to research all these cases ourselves. We hope they'll offer the correct numbers again, soon, and will update you if they don't. 110 | - The Robert Koch Institute keeps changing the format in which they show the [official numbers](https://www.rki.de/DE/Content/InfAZ/N/Neuartiges_Coronavirus/Fallzahlen.html) for **Germany**. We try to keep up and change our scraper, but we can't monitor it all the time. If the symbol map for Germany looks weird, please get in contact with us on Twitter at [@datawrapper](https://twitter.com/datawrapper). Thank you. 111 | - We also published a [Weekly Chart yesterday](/weekly-chart-coronavirus-growth/) that explains why #FlattenTheCurve is so important. Feel free to re-use it, too. You can find it at the top of this article. 112 | 113 | 114 | #### March 11 115 | 116 | - Added a map of Berlin. 117 | - Symbol maps now state the number of recovered and died COVID–19 patients in the tooltip. 118 | 119 | #### March 9 120 | 121 | - Fixed a bug that disabled the live updates when clicking on "Edit this chart". 122 | - Added Schleswig-Holstein to the map of German cases by state. 123 | - Added another very simple table without the relative terms. 124 | - Added a table with all countries. 125 | - Added a column chart with cases in Italy. 126 | - Added links to other data visualization designer who have thought about visualizing the coronavirus. 127 | - Added information about the licensing of Johns Hopkins data. 128 | - Edited information about the source of German maps. 129 | -------------------------------------------------------------------------------- /2020-04-02-website-colors/.gitignore: -------------------------------------------------------------------------------- 1 | *.png 2 | .mypy_cache 3 | .venv 4 | __pycache__ 5 | geckodriver.log 6 | -------------------------------------------------------------------------------- /2020-04-02-website-colors/README.md: -------------------------------------------------------------------------------- 1 | # Website Colors 2 | 3 | Take a screenshot of a website and print statistics about its colors. 4 | 5 | https://blog.datawrapper.de/weekly-chart-website-colors/ 6 | 7 | ## Prerequisites 8 | 9 | ### Mac 10 | 11 | ``` shell 12 | $ brew install python geckodriver 13 | ``` 14 | 15 | ### Arch Linux 16 | 17 | ``` shell 18 | # pacman -S pipenv geckodriver 19 | ``` 20 | 21 | ### Other systems 22 | 23 | Install these dependencies manually: 24 | 25 | - Python >= 3.6 26 | - geckodriver 27 | 28 | ## Setup 29 | 30 | Create Python virtual environment and install the requirements: 31 | 32 | ``` shell 33 | $ python -m virtualenv .venv 34 | $ source .venv/bin/activate 35 | $ pip install -r requirements.txt 36 | ``` 37 | 38 | ## Usage 39 | 40 | Activate the virtual environment: 41 | 42 | ``` shell 43 | $ source .venv/bin/activate 44 | ``` 45 | 46 | Run `website_colors.py` with the two required arguments: 47 | 48 | - `--url` or `-u`: the website to take the screenshot of 49 | - `--screenshot-path` or `-s`: the path to store the screenshot PNG 50 | 51 | Example: 52 | 53 | ``` shell 54 | $ ./website_colors.py -u https://www.datawrapper.de/ -s datawrapper.png 55 | ``` 56 | 57 | The script will then output the color statistics in CSV format to the standard 58 | output. 59 | 60 | Example: 61 | 62 | ``` csv 63 | color,frequency 64 | #a0a0a0,0.0009525772977887732 65 | #d0d0d0,0.0003235168181169418 66 | #707070,0.0005064201172484155 67 | #606060,0.0005888851885331261 68 | #505050,0.0006132018121170793 69 | #808080,0.0013596164316940758 70 | #c0c0c0,0.0010117829899931807 71 | #e0e0e0,0.0005053628727447652 72 | #000000,0.004619101236447447 73 | #b0b0b0,0.0011809421105772025 74 | #404040,0.09185763145513846 75 | #f0f0f0,0.1691200025373868 76 | ``` 77 | 78 | Note that if the screenshot PNG already exists, it will be used to calculate the 79 | statistics and no new screenshot will be made. 80 | -------------------------------------------------------------------------------- /2020-04-02-website-colors/requirements.txt: -------------------------------------------------------------------------------- 1 | pandas==1.0.3 2 | Pillow==8.3.2 3 | selenium==3.141.0 4 | -------------------------------------------------------------------------------- /2020-04-02-website-colors/website_colors.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import argparse 4 | import sys 5 | from colorsys import rgb_to_hsv 6 | from pathlib import Path 7 | from typing import Tuple 8 | 9 | import pandas as pd 10 | from PIL import Image, ImageOps 11 | 12 | from selenium import webdriver 13 | 14 | 15 | def color_8bit_to_float(color_8bit: Tuple[int, ...]) -> Tuple[float, ...]: 16 | return tuple(x / 255 for x in color_8bit) 17 | 18 | 19 | def rgb_to_hex(rgb: Tuple[float, float, float]) -> str: 20 | r, g, b = (round(x * 255) for x in rgb) 21 | return f'#{r:02x}{g:02x}{b:02x}' 22 | 23 | 24 | def hex_to_rgb(h: str) -> Tuple[float, ...]: 25 | return tuple(int(h[i : i + 2], 16) / 255 for i in (1, 3, 5)) 26 | 27 | 28 | def hex_to_h(h: str) -> float: 29 | rgb = hex_to_rgb(h) 30 | hsv = rgb_to_hsv(*rgb) 31 | return hsv[0] 32 | 33 | 34 | def take_screenshot(url: str, path: str): 35 | options = webdriver.FirefoxOptions() 36 | options.headless = True 37 | driver = webdriver.Firefox(options=options) 38 | driver.get(url) 39 | try: 40 | driver.save_screenshot(path) 41 | finally: 42 | driver.quit() 43 | 44 | 45 | def analyze_image( 46 | path: str, posterize_bits: int = 4, min_frequency: float = 0.0001, 47 | ) -> pd.Series: 48 | im = Image.open(path).convert(mode='RGB') 49 | im = ImageOps.posterize(im, posterize_bits) 50 | pixels = pd.Series(list(im.getdata()), name='frequency') 51 | pixels = pixels.apply(color_8bit_to_float) 52 | pixels = pixels.apply(rgb_to_hex) 53 | counts = pixels.value_counts(normalize=True) 54 | counts = counts[counts > min_frequency] 55 | counts = counts / counts.sum() 56 | df = pd.DataFrame( 57 | { 58 | 'frequency': counts.values, 59 | 'h': counts.index.to_series().apply(hex_to_h), 60 | }, 61 | index=counts.index, 62 | ) 63 | df.sort_values(by='h', inplace=True) 64 | return df['frequency'] 65 | 66 | 67 | def main(): 68 | parser = argparse.ArgumentParser() 69 | parser.add_argument('-u', '--url', required=True) 70 | parser.add_argument('-s', '--screenshot-path', required=True) 71 | args = parser.parse_args() 72 | if not Path(args.screenshot_path).exists(): 73 | take_screenshot(args.url, args.screenshot_path) 74 | counts = analyze_image(args.screenshot_path) 75 | counts.to_csv(sys.stdout, index_label='color') 76 | 77 | 78 | if __name__ == '__main__': 79 | main() 80 | -------------------------------------------------------------------------------- /2020-04-30-most-expensive-records/README.md: -------------------------------------------------------------------------------- 1 | # Top 100 most expensive music records sold on Discogs 2 | 3 | This is a collection of node.js scripts used to scrape the Discogs blog to get a list of top 100 most expensive records sold on its marketplace. 4 | 5 | The scripts need to be executed in the following order and do the following: 6 | 7 | 1. [get_top100_post.js](https://github.com/datawrapper/snippets/blob/master/2020-04-30-most-expensive-records/get_top100_post.js) outputs a list of releases in JSON format by scraping the top 100 blog post from March 2019 8 | 2. [get_monthly_posts.js](https://github.com/datawrapper/snippets/blob/master/2020-04-30-most-expensive-records/get_monthly_posts.js) outputs a list of releases in JSON format by scraping monthly top 30 posts from March 2019 to February 2020 9 | 3. [create_final100.js](https://github.com/datawrapper/snippets/blob/master/2020-04-30-most-expensive-records/create_final100.js) combines the two lists from above, sorts them by price and outputs the final top 100 list in JSON format 10 | 4. [download_images.js](https://github.com/datawrapper/snippets/blob/master/2020-04-30-most-expensive-records/download_images.js) downloads and resizes images from the final list 11 | 5. [export.js](https://github.com/datawrapper/snippets/blob/master/2020-04-30-most-expensive-records/export.js) formats final list and outputs the dataset in CSV format (you need to enter a path where you will host your images here) 12 | 13 | The following table was created using the dataset: 14 | 15 | ![Top 100 most expensive music records sold on Discogs](https://img.datawrapper.de/klGf1/full.png) 16 | 17 | ### Related links 18 | 19 | * [Interactive table](https://www.datawrapper.de/_/klGf1/) 20 | * [Weekly chart article](https://blog.datawrapper.de/weekly-chart-top-100-expensive-music-records/) 21 | 22 | ### Notes 23 | 24 | You need to have [node.js](https://nodejs.org/en/) and [npm](https://www.npmjs.com/) installed on your system in order to run these scripts. Install required packages first by running `npm i`. Execute the scripts by running `node [scriptname].js`. 25 | -------------------------------------------------------------------------------- /2020-04-30-most-expensive-records/create_final100.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const top100 = require('./output_top100_post.json'); 3 | const monthly = require('./output_monthly_posts.json'); 4 | 5 | const json = [...top100, ...monthly]; 6 | 7 | json.map((item) => (item.price = parseFloat(item.price))); 8 | json.sort((a, b) => b.price - a.price); 9 | const final100 = json.slice(0, 100); 10 | 11 | fs.writeFile('final100.json', JSON.stringify(final100), (error) => { 12 | if (error) throw error; 13 | console.log('File written!'); 14 | }); 15 | -------------------------------------------------------------------------------- /2020-04-30-most-expensive-records/download_images.js: -------------------------------------------------------------------------------- 1 | const axios = require('axios'); 2 | const sharp = require('sharp'); 3 | const fs = require('fs'); 4 | const json = require('./final100.json'); 5 | 6 | json.forEach((item) => { 7 | const url = item.imageUrl; 8 | const fileName = url.substring(url.lastIndexOf('/') + 1).replace('.jpeg', ''); 9 | const resizer = sharp().resize(128, 128); 10 | 11 | axios({ 12 | method: 'get', 13 | url, 14 | responseType: 'stream', 15 | }) 16 | .then((response) => { 17 | console.log(`downloaded: ${fileName}`); 18 | response.data.pipe(resizer).pipe(fs.createWriteStream(`./img/${fileName}`)); 19 | }) 20 | .catch((error) => { 21 | console.log(error); 22 | }); 23 | }); 24 | -------------------------------------------------------------------------------- /2020-04-30-most-expensive-records/export.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const json = require('./final100.json'); 3 | 4 | let output = 'Artist;Title;Sold for (in USD);Released in;Image\n'; 5 | 6 | json.forEach((item) => { 7 | const title = `[${item.title}](${item.url})`; 8 | 9 | // you need to enter a path where you will host images 10 | const path = 'https://your/path'; 11 | const imageUrl = `${path}/${item.imageUrl 12 | .substring(item.imageUrl.lastIndexOf('/') + 1) 13 | .replace('.jpeg', '')}`; 14 | const image = `![${item.artist} – ${item.title}](${imageUrl})`; 15 | 16 | const date = date || 'Unknown'; 17 | 18 | output += `${item.artist};${title};${item.price};${item.date};${image}\n`; 19 | }); 20 | 21 | fs.writeFile('final.csv', output, (error) => { 22 | if (error) throw error; 23 | console.log('File written!'); 24 | }); 25 | -------------------------------------------------------------------------------- /2020-04-30-most-expensive-records/get_monthly_posts.js: -------------------------------------------------------------------------------- 1 | const cheerio = require('cheerio'); 2 | const axios = require('axios'); 3 | const fs = require('fs'); 4 | 5 | const all = []; 6 | 7 | function getMonthlyItems(urls) { 8 | setTimeout(() => { 9 | const url = urls[0]; 10 | console.log(`get: ${url}`); 11 | axios 12 | .get(url) 13 | .then((response) => { 14 | const html = response.data; 15 | const $ = cheerio.load(html); 16 | const items = []; 17 | $('.post-entry-content > ol > li').each((index, item) => { 18 | const $item = $(item); 19 | 20 | const $artistTitle = $item.find('h4 > a'); 21 | const artistTitle = $artistTitle.text().split('–'); 22 | const artist = artistTitle[0].trim(); 23 | const title = artistTitle[1].trim(); 24 | let url = $artistTitle.attr('href'); 25 | url = url.replace('/sell', ''); 26 | if (url.includes('?')) { 27 | url = url.substring(0, url.indexOf('?')); 28 | } 29 | 30 | const $p = $item.find('div > p'); 31 | const pText = $p.text(); 32 | 33 | const priceStartIndex = pText.indexOf('$'); 34 | const price = pText.substring( 35 | priceStartIndex + 1, 36 | pText.indexOf(' ', priceStartIndex) 37 | ); 38 | 39 | const dateSearchString = 'Released: '; 40 | let date = null; 41 | if (pText.includes(dateSearchString)) { 42 | const dateStartIndex = 43 | pText.indexOf(dateSearchString) + dateSearchString.length; 44 | date = parseInt( 45 | pText.substring(dateStartIndex, pText.indexOf('\n', dateStartIndex)), 46 | 10 47 | ); 48 | } 49 | 50 | const imageUrl = $item.find('a > img').attr('src'); 51 | 52 | items.push({ artist, title, price, url, imageUrl, date }); 53 | }); 54 | 55 | all.push(...items); 56 | 57 | urls.shift(); 58 | if (urls.length === 0) return writeFile(); 59 | getMonthlyItems(urls); 60 | }) 61 | .catch((error) => { 62 | console.log(error); 63 | }); 64 | }, 500); 65 | } 66 | 67 | function writeFile() { 68 | fs.writeFile('output_monthly_posts.json', JSON.stringify(all), (error) => { 69 | if (error) throw error; 70 | console.log('File written!'); 71 | }); 72 | } 73 | 74 | const urls = [ 75 | 'https://blog.discogs.com/en/top-30-most-expensive-items-sold-in-discogs-marketplace-for-february-2020/', 76 | 'https://blog.discogs.com/en/top-30-most-expensive-items-sold-in-discogs-marketplace-for-january-2020/', 77 | 'https://blog.discogs.com/en/top-30-most-expensive-items-sold-in-discogs-marketplace-for-december-2019/', 78 | 'https://blog.discogs.com/en/top-30-most-expensive-items-sold-in-discogs-marketplace-for-november-2019/', 79 | 'https://blog.discogs.com/en/top-30-most-expensive-items-sold-in-discogs-marketplace-for-october-2019/', 80 | 'https://blog.discogs.com/en/top-30-most-expensive-items-sold-in-discogs-marketplace-for-september-2019/', 81 | 'https://blog.discogs.com/en/top-30-most-expensive-items-sold-in-discogs-marketplace-for-august-2019/', 82 | 'https://blog.discogs.com/en/top-30-most-expensive-items-sold-in-discogs-marketplace-for-july-2019/', 83 | 'https://blog.discogs.com/en/top-30-most-expensive-items-sold-in-discogs-marketplace-for-june-2019/', 84 | 'https://blog.discogs.com/en/top-30-most-expensive-may-2019/', 85 | 'https://blog.discogs.com/en/top-30-most-expensive-items-sold-in-discogs-marketplace-for-april-2019/', 86 | 'https://blog.discogs.com/en/top-30-most-expensive-items-sold-in-discogs-marketplace-for-march-2019/', 87 | ]; 88 | 89 | getMonthlyItems(urls); 90 | -------------------------------------------------------------------------------- /2020-04-30-most-expensive-records/get_top100_post.js: -------------------------------------------------------------------------------- 1 | const cheerio = require('cheerio'); 2 | const axios = require('axios'); 3 | const fs = require('fs'); 4 | 5 | const itemsWithDates = []; 6 | 7 | function getDate(items) { 8 | setTimeout(() => { 9 | const item = items[0]; 10 | console.log(`get: ${item.url}`); 11 | axios 12 | .get(item.url) 13 | .then((response) => { 14 | const html = response.data; 15 | const $ = cheerio.load(html); 16 | const $profile = $('.profile'); 17 | 18 | const $releasedHead = $('.profile .head').filter(function() { 19 | return $(this).text() === 'Released:'; 20 | }); 21 | 22 | const date = $releasedHead 23 | .next() 24 | .find('a') 25 | .text() 26 | .trim(); 27 | const d = new Date(date); 28 | item.date = d.getFullYear(); 29 | itemsWithDates.push(item); 30 | 31 | items.shift(); 32 | if (items.length === 0) return writeFile(); 33 | getDate(items); 34 | }) 35 | .catch((error) => { 36 | console.log(error); 37 | }); 38 | }, 500); 39 | } 40 | 41 | function writeFile() { 42 | fs.writeFile('output_top100_post.json', JSON.stringify(itemsWithDates), (error) => { 43 | if (error) throw error; 44 | console.log('File written!'); 45 | }); 46 | } 47 | 48 | axios 49 | .get('https://blog.discogs.com/en/discogs-top-100-most-expensive-records/') 50 | .then((response) => { 51 | const html = response.data; 52 | const $ = cheerio.load(html); 53 | const items = []; 54 | $('.post-entry-content > ol > li').each((index, item) => { 55 | const $item = $(item); 56 | 57 | const $artistTitle = $item.find('.artist-title a'); 58 | const artistTitle = $artistTitle.text().split('–'); 59 | const artist = artistTitle[0].trim(); 60 | const title = artistTitle[1].trim(); 61 | const url = $artistTitle.attr('href'); 62 | const price = $item 63 | .find('.price > h4') 64 | .text() 65 | .replace('$', '') 66 | .replace(',', ''); 67 | const imageUrl = $item.find('.album-artwork img').attr('src'); 68 | 69 | items.push({ artist, title, price, url, imageUrl }); 70 | }); 71 | 72 | getDate(items); 73 | }) 74 | .catch((error) => { 75 | console.log(error); 76 | }); 77 | -------------------------------------------------------------------------------- /2020-04-30-most-expensive-records/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "top-100-expensive-releases", 3 | "version": "1.0.0", 4 | "description": "Scripts used to get top 100 most expensive releases from the Discogs blog", 5 | "main": "export.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "Ivan Lokhov", 10 | "license": "UNLICENSED", 11 | "dependencies": { 12 | "axios": "^0.19.2", 13 | "cheerio": "^1.0.0-rc.3", 14 | "sharp": "^0.25.2" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /2020-05-28-excess-mortality/2020-05-26_stmf_raw.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2020-05-28-excess-mortality/2020-05-26_stmf_raw.xlsx -------------------------------------------------------------------------------- /2020-05-28-excess-mortality/README.md: -------------------------------------------------------------------------------- 1 | ## Download and process excess mortality data 2 | 3 | A set of simple R scripts for processing excess mortality data from two different sources for use in Datawrapper: 4 | 5 | - [Short-term Mortality Fluctuations (STMF) from The Human Mortality Database](https://mortality.org) 6 | - [The NYT repo of data on excesss death during the coronavirus pandemic](https://github.com/nytimes/covid-19-data/tree/master/excess-deaths) 7 | 8 | The scripts were used for creating the charts in the following blog post: [The coronavirus death toll](https://blog.datawrapper.de/weekly-chart-covid19-excess-mortality/). 9 | 10 | ### How to use the scripts: 11 | 12 | - There's one script per region 13 | - Run them in R-Studio to prepare wide table CSV files for the respective regions 14 | - CSV files get stored into `./data`. 15 | - Upload those files to [Datawrapper](https://datawrapper.de) to create charts 16 | -------------------------------------------------------------------------------- /2020-05-28-excess-mortality/aut-excess-mortality.R: -------------------------------------------------------------------------------- 1 | needs(tidyverse) 2 | needs(readxl) 3 | 4 | raw_data <- read_excel("2020-05-26_stmf_raw.xlsx", sheet = "AUT", col_types = c("text", 5 | "numeric", "numeric", "text", "numeric", 6 | "numeric", "numeric", "numeric", 7 | "numeric", "numeric", "skip", "skip", 8 | "skip", "skip", "skip", "skip", "numeric", 9 | "numeric", "numeric"), skip = 2) 10 | 11 | past_years <- c(as.character(2000:2019)) 12 | 13 | output <- raw_data %>% 14 | filter(Sex == "b") %>% # do not differentiate by gender 15 | head(-1) %>% # remove last week, which may be incomplete 16 | select(Country, Year, Week, Total) %>% # select relevant columns 17 | pivot_wider(names_from = Year, values_from = Total) %>% # pivot to wide table 18 | mutate( 19 | Average = rowMeans(select(., past_years)), # calculate mean 20 | Date = as.Date(paste(2020, Week, 1, sep="-"), "%Y-%U-%u"), 21 | Baseline = 0 22 | ) 23 | 24 | View(output) 25 | 26 | output %>% write_csv('data/aut.csv', na = '') 27 | -------------------------------------------------------------------------------- /2020-05-28-excess-mortality/bel-excess-mortality.R: -------------------------------------------------------------------------------- 1 | needs(tidyverse) 2 | needs(readxl) 3 | 4 | raw_data <- read_excel("2020-05-26_stmf_raw.xlsx", sheet = "BEL", col_types = c("text", 5 | "numeric", "numeric", "text", "numeric", 6 | "numeric", "numeric", "numeric", 7 | "numeric", "numeric", "skip", "skip", 8 | "skip", "skip", "skip", "skip", "numeric", 9 | "numeric", "numeric"), skip = 2) 10 | 11 | past_years <- c(as.character(2000:2019)) 12 | 13 | output <- raw_data %>% 14 | filter(Sex == "b") %>% # do not differentiate by gender 15 | head(-1) %>% # remove last week, which may be incomplete 16 | select(Country, Year, Week, Total) %>% # select relevant columns 17 | pivot_wider(names_from = Year, values_from = Total) %>% # pivot to wide table 18 | mutate( 19 | Average = rowMeans(select(., past_years)), # calculate mean 20 | Date = as.Date(paste(2020, Week, 1, sep="-"), "%Y-%U-%u"), 21 | Baseline = 0 22 | ) 23 | 24 | View(output) 25 | 26 | output %>% write_csv('data/bel.csv', na = '') 27 | -------------------------------------------------------------------------------- /2020-05-28-excess-mortality/covid19-mortality.Rproj: -------------------------------------------------------------------------------- 1 | Version: 1.0 2 | 3 | RestoreWorkspace: Default 4 | SaveWorkspace: Default 5 | AlwaysSaveHistory: Default 6 | 7 | EnableCodeIndexing: Yes 8 | UseSpacesForTab: Yes 9 | NumSpacesForTab: 2 10 | Encoding: UTF-8 11 | 12 | RnwWeave: Sweave 13 | LaTeX: pdfLaTeX 14 | -------------------------------------------------------------------------------- /2020-05-28-excess-mortality/data/aut.csv: -------------------------------------------------------------------------------- 1 | Country,Week,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,2020,Average,Date,Baseline 2 | AUT,1,1867,1580,1632,1661,1718,1534,1504,1576,1686,1681,1557,1579,1574,1637,1549,1704,1634,2293,1767,1647,1607,1669,2020-01-06,0 3 | AUT,2,1902,1600,1551,1611,1649,1564,1473,1537,1705,1775,1582,1671,1563,1659,1543,1768,1626,2340,1842,1709,1700,1683.5,2020-01-13,0 4 | AUT,3,2027,1460,1523,1619,1661,1678,1559,1416,1624,1915,1573,1513,1586,1612,1578,1837,1608,2060,1786,1641,1797,1663.8,2020-01-20,0 5 | AUT,4,1940,1566,1639,1618,1658,1570,1524,1459,1583,1992,1573,1560,1595,1584,1463,1792,1578,1938,1714,1713,1777,1652.95,2020-01-27,0 6 | AUT,5,1928,1529,1572,1625,1723,1681,1489,1545,1610,1974,1544,1521,1545,1752,1574,1837,1609,2045,1870,1732,1946,1685.25,2020-02-03,0 7 | AUT,6,1760,1473,1543,1594,1614,1774,1658,1554,1518,1920,1551,1598,1760,1748,1677,1926,1650,1874,1938,1796,1677,1696.3,2020-02-10,0 8 | AUT,7,1666,1432,1555,1688,1581,1853,1478,1556,1532,1723,1598,1622,1895,1815,1671,1992,1621,1750,1881,1820,1720,1686.45,2020-02-17,0 9 | AUT,8,1628,1514,1605,1843,1521,1813,1525,1667,1509,1751,1647,1586,1796,1711,1600,2020,1581,1807,1951,1751,1712,1691.3,2020-02-24,0 10 | AUT,9,1566,1438,1465,1881,1604,1841,1434,1615,1583,1715,1554,1520,1805,1668,1623,1883,1714,1696,2021,1764,1765,1669.5,2020-03-02,0 11 | AUT,10,1524,1488,1565,1904,1526,1695,1500,1549,1484,1619,1554,1597,1762,1729,1564,1846,1532,1614,1965,1811,1731,1641.4,2020-03-09,0 12 | AUT,11,1528,1511,1581,1766,1473,1614,1476,1536,1504,1479,1560,1588,1763,1690,1647,1763,1516,1542,1946,1790,1707,1613.65,2020-03-16,0 13 | AUT,12,1501,1518,1482,1654,1439,1494,1513,1514,1476,1446,1578,1555,1650,1684,1607,1696,1499,1535,1641,1619,1826,1555.05,2020-03-23,0 14 | AUT,13,1428,1360,1399,1597,1480,1448,1592,1445,1499,1493,1509,1497,1653,1650,1492,1725,1598,1489,1766,1651,1749,1538.55,2020-03-30,0 15 | AUT,14,1475,1445,1527,1524,1431,1477,1458,1437,1499,1473,1352,1463,1508,1611,1590,1604,1562,1537,1617,1607,,1509.85,2020-04-06,0 16 | AUT,15,1543,1506,1531,1452,1408,1439,1412,1428,1505,1492,1486,1426,1499,1627,1497,1563,1520,1532,1560,1556,,1499.1,2020-04-13,0 17 | AUT,16,1391,1441,1447,1432,1404,1358,1428,1373,1491,1446,1442,1482,1499,1569,1538,1614,1413,1475,1557,1558,,1467.9,2020-04-20,0 18 | AUT,17,1392,1509,1390,1415,1371,1373,1360,1405,1375,1436,1453,1482,1525,1532,1476,1547,1460,1440,1383,1521,,1442.25,2020-04-27,0 19 | AUT,18,1290,1508,1433,1410,1390,1371,1391,1403,1392,1350,1446,1402,1516,1407,1536,1453,1447,1527,1434,1462,,1428.4,2020-05-04,0 20 | AUT,19,1279,1402,1439,1490,1272,1417,1446,1341,1395,1458,1410,1470,1437,1432,1539,1452,1486,1434,1372,1453,,1421.2,2020-05-11,0 21 | AUT,20,1320,1361,1415,1345,1386,1361,1371,1328,1391,1347,1388,1347,1450,1443,1405,1461,1453,1501,1342,1558,,1398.65,2020-05-18,0 22 | AUT,21,1336,1312,1379,1353,1340,1438,1411,1484,1386,1439,1425,1473,1457,1398,1515,1396,1505,1327,1383,1497,,1412.7,2020-05-25,0 23 | AUT,22,1265,1354,1352,1419,1328,1233,1341,1332,1383,1374,1455,1353,1379,1477,1442,1304,1402,1456,1415,1495,,1377.95,2020-06-01,0 24 | AUT,23,1383,1291,1357,1410,1352,1279,1387,1307,1334,1335,1582,1382,1419,1460,1407,1437,1360,1312,1433,1520,,1387.35,2020-06-08,0 25 | AUT,24,1428,1335,1418,1475,1370,1388,1500,1346,1332,1348,1326,1340,1344,1435,1476,1502,1348,1421,1392,1554,,1403.9,2020-06-15,0 26 | AUT,25,1392,1351,1664,1271,1317,1361,1480,1385,1291,1327,1359,1381,1557,1631,1440,1285,1452,1476,1401,1424,,1412.25,2020-06-22,0 27 | AUT,26,1317,1413,1469,1382,1307,1271,1417,1309,1377,1330,1509,1349,1470,1358,1503,1374,1338,1419,1414,1454,,1389,2020-06-29,0 28 | AUT,27,1339,1349,1395,1374,1307,1227,1287,1185,1349,1311,1451,1462,1570,1426,1398,1487,1328,1413,1441,1507,,1380.3,2020-07-06,0 29 | AUT,28,1304,1365,1364,1340,1308,1324,1409,1373,1311,1328,1673,1427,1337,1369,1391,1476,1323,1346,1404,1338,,1375.5,2020-07-13,0 30 | AUT,29,1329,1338,1320,1422,1302,1225,1413,1743,1307,1445,1373,1330,1353,1422,1438,1475,1458,1475,1511,1430,,1405.45,2020-07-20,0 31 | AUT,30,1299,1293,1346,1451,1401,1472,1476,1422,1310,1383,1327,1324,1442,1542,1427,1633,1424,1375,1455,1557,,1417.95,2020-07-27,0 32 | AUT,31,1375,1472,1360,1428,1317,1320,1303,1285,1399,1354,1342,1356,1394,1605,1326,1446,1390,1616,1615,1457,,1408,2020-08-03,0 33 | AUT,32,1326,1327,1339,1464,1335,1287,1244,1369,1270,1331,1422,1318,1313,1634,1404,1500,1359,1334,1532,1406,,1375.7,2020-08-10,0 34 | AUT,33,1519,1448,1346,1476,1299,1280,1384,1314,1329,1314,1369,1420,1337,1390,1331,1692,1394,1380,1430,1407,,1392.95,2020-08-17,0 35 | AUT,34,1441,1409,1300,1310,1289,1284,1337,1316,1278,1462,1427,1517,1507,1359,1381,1376,1408,1472,1460,1453,,1389.3,2020-08-24,0 36 | AUT,35,1279,1294,1396,1303,1226,1294,1359,1297,1314,1289,1309,1376,1311,1324,1416,1476,1414,1329,1414,1501,,1346.05,2020-08-31,0 37 | AUT,36,1217,1253,1311,1351,1287,1295,1392,1288,1343,1319,1378,1380,1385,1481,1446,1389,1380,1318,1376,1423,,1350.6,2020-09-07,0 38 | AUT,37,1382,1306,1291,1324,1292,1275,1301,1348,1350,1325,1339,1270,1401,1365,1392,1447,1392,1426,1452,1407,,1354.25,2020-09-14,0 39 | AUT,38,1303,1304,1350,1353,1232,1295,1334,1291,1347,1406,1483,1431,1399,1446,1454,1459,1376,1407,1421,1452,,1377.15,2020-09-21,0 40 | AUT,39,1351,1399,1396,1385,1294,1301,1326,1366,1395,1340,1493,1349,1488,1381,1407,1410,1442,1496,1436,1574,,1401.45,2020-09-28,0 41 | AUT,40,1353,1406,1456,1357,1352,1422,1348,1364,1496,1348,1490,1392,1425,1418,1473,1494,1469,1481,1553,1555,,1432.6,2020-10-05,0 42 | AUT,41,1422,1399,1420,1387,1341,1394,1335,1356,1457,1455,1465,1440,1436,1506,1478,1409,1556,1529,1509,1592,,1444.3,2020-10-12,0 43 | AUT,42,1415,1454,1409,1396,1369,1426,1391,1437,1453,1356,1477,1447,1512,1437,1449,1481,1607,1453,1488,1497,,1447.7,2020-10-19,0 44 | AUT,43,1409,1362,1462,1463,1475,1411,1440,1391,1411,1509,1403,1465,1487,1474,1476,1498,1522,1489,1491,1545,,1459.15,2020-10-26,0 45 | AUT,44,1466,1406,1410,1508,1420,1396,1332,1464,1413,1479,1528,1476,1543,1407,1457,1433,1484,1551,1561,1536,,1463.5,2020-11-02,0 46 | AUT,45,1578,1439,1512,1457,1338,1388,1418,1506,1348,1436,1426,1419,1498,1457,1567,1460,1541,1490,1501,1555,,1466.7,2020-11-09,0 47 | AUT,46,1372,1513,1498,1397,1436,1436,1461,1499,1394,1398,1400,1504,1485,1467,1487,1527,1616,1505,1556,1558,,1475.45,2020-11-16,0 48 | AUT,47,1441,1500,1458,1429,1439,1472,1488,1481,1421,1461,1445,1564,1515,1490,1517,1486,1550,1570,1531,1553,,1490.55,2020-11-23,0 49 | AUT,48,1406,1484,1442,1393,1503,1546,1327,1417,1476,1438,1527,1536,1456,1463,1541,1488,1601,1531,1525,1586,,1484.3,2020-11-30,0 50 | AUT,49,1388,1495,1525,1439,1500,1419,1422,1525,1473,1446,1631,1533,1524,1529,1566,1509,1619,1632,1656,1599,,1521.5,2020-12-07,0 51 | AUT,50,1471,1570,1588,1348,1519,1474,1395,1466,1487,1489,1654,1576,1678,1524,1586,1517,1670,1554,1626,1667,,1542.95,2020-12-14,0 52 | AUT,51,1459,1638,1614,1455,1475,1472,1495,1465,1487,1507,1609,1581,1594,1504,1601,1538,1847,1653,1639,1591,,1561.2,2020-12-21,0 53 | AUT,52,1513,1617,1604,1549,1532,1530,1514,1556,1563,1577,1544,1606,1599,1537,1625,1545,2160,1646,1689,1636,,1607.1,2020-12-28,0 54 | -------------------------------------------------------------------------------- /2020-05-28-excess-mortality/data/bel.csv: -------------------------------------------------------------------------------- 1 | Country,Week,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,2020,Average,Date,Baseline 2 | BEL,1,2814,2282,2432,2260,2436,2339,2247,2213,2407,2246,2280,2334,2286,2236,2214,2461,2244,2557,2382,2308,2224,2348.9,2020-01-06,0 3 | BEL,2,2761,2244,2484,2238,2536,2292,2169,2197,2371,2466,2352,2323,2218,2267,2200,2525,2234,2735,2317,2347,2380,2363.8,2020-01-13,0 4 | BEL,3,2640,2300,2542,2247,2312,2277,2220,2186,2343,2635,2303,2191,2232,2238,2136,2526,2295,2645,2336,2312,2303,2345.8,2020-01-20,0 5 | BEL,4,2633,2302,2573,2220,2162,2181,2152,2020,2207,2612,2226,2030,2233,2444,2090,2510,2263,2691,2253,2395,2190,2309.85,2020-01-27,0 6 | BEL,5,2403,2241,2473,2220,2240,2292,2076,2115,2142,2525,2248,2144,2358,2576,2190,2644,2180,2950,2355,2421,2354,2339.65,2020-02-03,0 7 | BEL,6,2201,2239,2369,2237,2136,2337,2164,2294,2072,2601,2151,2066,2445,2448,2225,2727,2127,2691,2353,2544,2161,2321.35,2020-02-10,0 8 | BEL,7,2168,2055,2173,2157,2003,2369,2203,2278,2156,2508,2260,2068,2717,2444,2167,2892,2121,2631,2565,2409,2298,2317.2,2020-02-17,0 9 | BEL,8,2127,1988,2179,2266,2044,2357,2128,2325,2192,2248,2210,2053,2770,2435,2196,2774,2230,2389,2628,2418,2287,2297.85,2020-02-24,0 10 | BEL,9,2055,2134,2086,2293,2105,2464,2104,2255,2168,2319,2116,1972,2650,2549,2131,2643,2336,2315,3002,2428,2231,2306.25,2020-03-02,0 11 | BEL,10,2029,2177,2156,2224,2032,2457,2112,2132,2056,2184,2144,2144,2480,2572,2070,2457,2264,2138,3016,2389,2202,2261.65,2020-03-09,0 12 | BEL,11,2012,2016,2104,2157,2002,2435,2173,2015,2159,2011,2092,2077,2427,2343,2198,2380,2248,2036,2724,2335,2214,2197.2,2020-03-16,0 13 | BEL,12,1931,1960,2020,2009,2093,2263,2113,1921,2130,1969,2036,2049,2162,2364,2152,2380,2364,2106,2594,2167,2543,2139.15,2020-03-23,0 14 | BEL,13,1894,2050,2006,2113,1934,2071,2101,2000,2150,1951,2024,2014,2206,2365,2048,2270,2273,2068,2460,2063,3175,2103.05,2020-03-30,0 15 | BEL,14,1973,2107,2090,2021,1986,1997,1958,2028,2235,1932,1918,1936,2099,2418,2175,2163,2080,1969,2203,2183,4016,2073.55,2020-04-06,0 16 | BEL,15,2002,1892,2025,2128,1877,1965,2052,1988,2164,2008,1948,1898,2122,2415,2028,2218,2160,1954,2175,1969,4271,2049.4,2020-04-13,0 17 | BEL,16,1952,1986,2034,2251,2042,1889,1893,1986,2136,1937,1929,2046,2110,2254,1920,2152,2049,1917,2044,2095,3689,2031.1,2020-04-20,0 18 | BEL,17,1966,1989,2041,2122,1892,1976,1893,1915,2072,1954,1956,1934,2027,2139,2017,2087,1996,2079,1953,2046,3014,2002.7,2020-04-27,0 19 | BEL,18,1907,2021,1892,1980,1887,1829,1969,1834,2007,1869,1894,1882,2091,1940,1892,2005,2087,2091,1867,2011,2393,1947.75,2020-05-04,0 20 | BEL,19,1953,2096,1883,1962,1816,1835,1826,1740,1981,1737,1967,1962,2020,1960,1936,2063,2065,2009,1980,2034,,1941.25,2020-05-11,0 21 | BEL,20,1834,1929,1998,1860,1857,1949,1881,1820,2041,1786,1989,1872,1879,1988,2000,1976,1926,2110,1860,2034,,1929.45,2020-05-18,0 22 | BEL,21,1789,1923,1877,1833,1825,2033,1741,1858,1877,1834,1886,1959,2086,1984,1948,1950,1946,2009,1951,1995,,1915.2,2020-05-25,0 23 | BEL,22,1864,2008,1866,2067,1809,1855,1802,1795,1808,1875,2029,1997,1904,2017,1957,1905,1885,1981,1953,1933,,1915.5,2020-06-01,0 24 | BEL,23,1937,1892,1952,2010,1885,1746,1866,1931,1778,1850,1882,1870,1897,2179,1948,1942,1856,1815,1811,1966,,1900.65,2020-06-08,0 25 | BEL,24,1799,1959,1878,1900,1905,1899,2060,1823,1836,1877,1736,1888,1845,1999,1898,2003,1851,1868,1734,1847,,1880.25,2020-06-15,0 26 | BEL,25,2026,1936,1922,1873,1799,2057,1878,1762,1853,1816,1961,1832,1902,2032,1853,1900,1920,2101,1779,1913,,1905.75,2020-06-22,0 27 | BEL,26,1919,1978,1824,1897,1799,1806,1810,1731,1903,1949,2200,2037,2016,1850,1865,1888,1846,1821,1950,1980,,1903.45,2020-06-29,0 28 | BEL,27,1922,2008,1842,1713,1853,1650,2038,1749,1886,1944,2063,1970,1864,1828,1867,2301,1899,1901,2080,1935,,1915.65,2020-07-06,0 29 | BEL,28,1794,1748,1863,1834,1753,1779,1762,1801,1792,1743,1871,1798,1816,1882,1853,1908,1933,1847,1833,1788,,1819.9,2020-07-13,0 30 | BEL,29,1781,1803,1782,2136,1845,1725,2228,1900,1711,1862,1842,1790,1774,1883,2039,1797,2030,1827,1988,1882,,1881.25,2020-07-20,0 31 | BEL,30,1901,1895,1902,1849,1823,1769,2286,1675,1812,1761,1752,1777,2041,2061,1999,1740,1917,1897,2107,2318,,1914.1,2020-07-27,0 32 | BEL,31,1871,1907,2134,1847,1889,1619,1751,1666,2060,1829,1785,1931,1771,1867,1905,1777,1801,1808,2125,1916,,1862.95,2020-08-03,0 33 | BEL,32,1927,1697,1728,2062,1932,1658,1703,1733,1784,1887,1816,1878,1834,1796,1815,1997,1788,1826,2000,1766,,1831.35,2020-08-10,0 34 | BEL,33,1904,1929,1888,2255,1803,1751,1788,1668,1679,1724,1853,1770,1838,1761,1707,1852,1976,1784,1887,1777,,1829.7,2020-08-17,0 35 | BEL,34,1846,1968,1941,1766,1697,1739,1687,1812,1729,1752,1798,1858,1954,1866,1783,1755,2120,1951,1824,1859,,1835.25,2020-08-24,0 36 | BEL,35,1671,1854,1854,1777,1703,1819,1777,1684,1802,1758,1804,1856,1731,1806,1881,1919,1866,1924,1825,2006,,1815.85,2020-08-31,0 37 | BEL,36,1811,1732,1829,1889,1803,1881,1788,1799,1723,1783,1826,1832,1790,1857,1893,1775,1835,1883,1909,1838,,1823.8,2020-09-07,0 38 | BEL,37,1744,1723,1789,1897,1791,1652,1914,1730,1736,1802,1911,1822,1845,1793,1837,1917,1938,1823,1811,1833,,1815.4,2020-09-14,0 39 | BEL,38,1840,1845,1812,1995,1731,1658,1712,1817,1811,1803,1981,1819,1788,1774,1912,1844,1769,1908,1970,1923,,1835.6,2020-09-21,0 40 | BEL,39,1891,1939,1847,1922,1825,1726,1749,1831,1845,1843,1952,2015,1996,2065,1792,1932,1906,1963,1831,1906,,1888.8,2020-09-28,0 41 | BEL,40,1852,1841,1986,1907,1837,1856,1798,1808,1846,1829,1955,1891,2015,2010,1861,1973,1904,1955,1965,2048,,1906.85,2020-10-05,0 42 | BEL,41,1961,1865,1928,1912,1844,1894,1789,1873,1994,1912,1813,1914,1965,1875,1882,2019,2065,2059,2006,1951,,1926.05,2020-10-12,0 43 | BEL,42,1826,1765,1941,1885,1938,1882,1811,1883,1899,1872,1950,1930,2050,2054,1930,2059,2041,2007,1957,1961,,1932.05,2020-10-19,0 44 | BEL,43,1889,1719,1962,1967,1993,1921,1840,1910,1893,2109,2005,2085,2018,1975,1967,2038,2025,1913,1918,2065,,1960.6,2020-10-26,0 45 | BEL,44,1966,1788,1935,2058,1853,1816,1729,2032,1969,1994,1955,2116,2007,1877,1942,2095,2088,1892,1907,1935,,1947.7,2020-11-02,0 46 | BEL,45,2072,1888,1965,1968,1841,1892,1826,2035,2009,1982,1972,1937,2095,1948,1922,1951,2093,1939,2049,2001,,1969.25,2020-11-09,0 47 | BEL,46,2021,1942,1930,2062,1932,1847,1994,2001,1957,1960,1925,2077,2030,1872,1976,1934,2177,2078,2017,2014,,1987.3,2020-11-16,0 48 | BEL,47,1964,2025,1941,2030,1914,1916,1914,2119,1999,2007,1996,2027,2079,2110,2024,2020,2143,2114,2060,2187,,2029.45,2020-11-23,0 49 | BEL,48,2031,1978,1943,2007,1948,2098,1908,2152,2046,1970,2147,2159,2061,2040,2105,2021,2191,2080,2107,2122,,2055.7,2020-11-30,0 50 | BEL,49,1911,1904,1984,2053,2023,2121,1914,2136,2169,1976,2172,2182,2152,2013,2088,1992,2221,2276,2173,2161,,2081.05,2020-12-07,0 51 | BEL,50,1925,2087,2165,2321,1950,2069,1938,2107,2143,1973,2288,2203,2184,2145,2285,2113,2221,2325,2233,2213,,2144.4,2020-12-14,0 52 | BEL,51,2006,2209,2298,2426,2117,2123,1980,2296,2211,2063,2312,2383,2292,2189,2326,2085,2321,2272,2263,2337,,2225.45,2020-12-21,0 53 | BEL,52,2177,2358,2292,2618,2240,2167,2069,2342,2217,2295,2311,2321,2203,2190,2279,2031,2418,2350,2251,2152,,2264.05,2020-12-28,0 54 | -------------------------------------------------------------------------------- /2020-05-28-excess-mortality/data/esp.csv: -------------------------------------------------------------------------------- 1 | Country,Week,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,2020,Average,Date,Baseline 2 | ESP,1,9414,8740,10026,9314,4972,10846,8240,9898,11851,5488,8205,8886,9765,9260,10528,5713,8658,10726,12363,8453,8192,9067.3,2020-01-06,0 3 | ESP,2,9875,7281,9076,7673,8649,11299,7923,8807,8982,9319,8640,8440,9131,8422,9009,10415,8671,11414,10905,9968,8928,9194.95,2020-01-13,0 4 | ESP,3,9626,7138,8968,8410,8053,11057,7936,8477,8690,9868,8322,8419,9241,8562,9126,10738,8791,11334,10981,10406,9426,9207.15,2020-01-20,0 5 | ESP,4,9426,7435,8798,8248,8005,10154,7665,8505,8150,9522,8063,8699,8936,8328,9061,10625,8491,11068,10324,10090,9398,8979.65,2020-01-27,0 6 | ESP,5,8759,7359,8845,8051,7669,10247,7936,9021,8095,8868,8154,8657,9256,8359,8867,11046,8461,10636,9893,9930,9470,8905.45,2020-02-03,0 7 | ESP,6,7858,7147,8518,8127,7597,9599,7862,9198,8283,8451,7954,8684,10064,8320,8996,10682,8556,9660,10015,9618,8765,8759.45,2020-02-10,0 8 | ESP,7,7514,7239,8186,7658,7339,8866,7978,8466,8347,8046,8283,8496,11103,8609,8829,10857,8479,9017,10105,9310,8377,8636.35,2020-02-17,0 9 | ESP,8,7219,7141,8079,8005,7481,8823,7577,8009,8188,7986,8059,8135,10993,8508,8396,10580,8670,8670,9656,9168,7941,8467.15,2020-02-24,0 10 | ESP,9,7014,7425,7874,7694,7579,8567,7893,8016,8190,7844,7471,7822,10535,8472,8252,10058,8645,8371,9599,8882,7930,8310.15,2020-03-02,0 11 | ESP,10,6918,7431,7821,7559,7952,9000,7956,7503,7796,7743,7498,7970,9309,8739,8107,9421,8653,8213,9203,8548,8005,8167,2020-03-09,0 12 | ESP,11,6647,6829,7545,7207,7751,8595,7597,7396,7908,7652,7778,7851,8907,7947,7813,8785,8811,7906,8862,8161,8545,7897.4,2020-03-16,0 13 | ESP,12,6566,6784,7442,7164,7417,7894,7300,7704,7518,7425,7568,7529,8088,8131,8034,8379,8291,7875,8616,7994,10841,7685.95,2020-03-23,0 14 | ESP,13,6846,6591,6847,7206,7171,7536,7248,7756,7731,7337,7237,7625,8135,7703,7728,8366,8375,7827,8628,8125,15525,7600.9,2020-03-30,0 15 | ESP,14,6793,6714,7205,7077,7211,7113,7014,7628,7738,7377,7299,7545,7759,7561,7743,8282,7998,7814,8414,8036,16217,7516.05,2020-04-06,0 16 | ESP,15,7011,6629,7029,7194,7070,7004,6869,7568,7496,7285,7476,7071,7626,7551,7635,7894,7859,7800,8335,8016,13985,7420.9,2020-04-13,0 17 | ESP,16,6793,6654,6995,7061,7278,7022,6735,7460,7347,7176,7156,6915,7683,7253,7258,7855,7589,7574,8112,7767,11129,7284.15,2020-04-20,0 18 | ESP,17,6553,6796,6999,7062,7029,6957,6851,7029,7322,7286,7228,7090,7551,7020,6999,7802,7462,7661,7735,7696,8986,7206.4,2020-04-27,0 19 | ESP,18,6627,6665,6629,6899,6832,6816,6776,6820,6981,6994,6815,6941,7394,7054,7307,7365,7606,7520,7359,7707,7963,7055.35,2020-05-04,0 20 | ESP,19,6305,6769,6466,6690,6827,6525,6699,7162,7075,7310,6884,6988,7625,7166,7344,7464,7374,7622,7595,7664,,7077.7,2020-05-11,0 21 | ESP,20,6392,6763,6617,6887,6745,6627,6865,7086,6527,7030,7272,6855,7235,7032,7049,7543,7533,7494,7511,7491,,7027.7,2020-05-18,0 22 | ESP,21,6052,6752,6562,6750,6927,6787,6523,6711,6775,7053,7159,7218,6972,6940,6904,7234,7304,7666,7527,7382,,6959.9,2020-05-25,0 23 | ESP,22,6630,7196,6385,6914,6624,6528,6484,6772,6440,6712,7162,6743,7010,6988,6832,7096,7255,7092,7306,7567,,6886.8,2020-06-01,0 24 | ESP,23,6147,6560,6270,6805,6512,6516,6817,6844,6556,6759,6475,6690,6771,7173,7136,7364,7576,7067,7109,7469,,6830.8,2020-06-08,0 25 | ESP,24,6538,6256,6802,7690,6590,6578,6588,6789,6771,6803,6496,6851,6499,7314,7404,7152,7140,7819,7154,6970,,6910.2,2020-06-15,0 26 | ESP,25,6324,6539,6981,7727,6421,6908,6629,6717,7015,7016,6808,7030,6589,6670,7248,6956,7173,7991,7713,7356,,6990.55,2020-06-22,0 27 | ESP,26,6309,6951,6698,7363,6395,6570,6600,6565,7283,6714,7220,7393,7267,6916,6852,7111,7345,7137,7698,7502,,6994.45,2020-06-29,0 28 | ESP,27,6385,6763,6470,6650,6868,6271,6630,6723,7127,7041,7355,6873,6451,7301,6851,8146,7505,7156,7305,7975,,6992.3,2020-07-06,0 29 | ESP,28,6071,6474,6217,7120,6223,6489,7154,6680,6754,6519,7298,6827,6675,7807,6736,8351,7423,7214,7366,7406,,6940.2,2020-07-13,0 30 | ESP,29,6359,6129,6504,6855,6274,6423,7433,6623,6645,6588,6888,6618,6612,7063,7065,8164,7377,7259,7186,7241,,6865.3,2020-07-20,0 31 | ESP,30,6152,6380,6525,7188,6738,6369,7349,6715,6673,6693,6648,6698,6844,6904,7127,7798,7295,7110,7155,7396,,6887.85,2020-07-27,0 32 | ESP,31,6355,7179,6477,7777,7034,6233,6883,7268,6953,6759,6651,6892,6742,6795,6867,7349,7425,7596,7731,7057,,7001.15,2020-08-03,0 33 | ESP,32,6200,6796,6068,8654,6693,6374,6554,6608,6870,6703,6752,6821,6959,6734,6891,7219,7233,7186,8003,7228,,6927.3,2020-08-10,0 34 | ESP,33,6489,6546,6116,8774,6507,6096,6142,6418,6764,6679,6545,7051,6842,6771,6724,7075,7102,7118,7194,7038,,6799.55,2020-08-17,0 35 | ESP,34,6119,6544,6043,7003,6296,6079,6449,6304,6577,6997,6822,6887,7157,6757,6643,6801,7184,7219,7015,6833,,6686.45,2020-08-24,0 36 | ESP,35,6056,6299,6044,6564,6381,6321,6586,6492,6379,6786,6557,6635,6536,6477,6995,6954,7100,7013,6927,6824,,6596.3,2020-08-31,0 37 | ESP,36,5964,6147,6042,6268,6277,5942,6755,6396,6375,6482,6410,6605,6652,6418,7057,6603,7203,6680,6906,6799,,6499.05,2020-09-07,0 38 | ESP,37,6077,6020,6034,6198,6235,6143,6275,6557,6289,6315,6329,6690,6524,6376,6687,6660,6641,6730,6834,6854,,6423.4,2020-09-14,0 39 | ESP,38,5693,6058,6220,6612,6158,6006,6389,6243,6378,6259,6486,6371,6644,6465,6626,6617,6956,7091,7153,6914,,6466.95,2020-09-21,0 40 | ESP,39,5899,6172,6180,6473,6200,6338,6475,6460,6161,6539,6655,6756,6268,6907,6508,6898,7036,7367,7230,6903,,6571.25,2020-09-28,0 41 | ESP,40,6260,6436,6267,6230,6296,6375,6342,6732,6539,6778,6942,6900,6662,6939,6930,6813,7072,7388,7210,6663,,6688.7,2020-10-05,0 42 | ESP,41,6382,6395,6390,6551,6609,6565,6572,6612,7096,6908,6682,7089,6845,6520,6987,7055,7036,7234,7437,6982,,6797.35,2020-10-12,0 43 | ESP,42,6603,6356,6611,6650,6621,6533,6686,7109,7047,6685,7074,7141,6867,6960,7265,7119,7185,7392,7350,6994,,6912.4,2020-10-19,0 44 | ESP,43,6614,6516,6646,6822,7021,6665,6841,6995,6846,7042,7305,7308,6696,7017,7322,7267,7512,7308,7327,7120,,7009.5,2020-10-26,0 45 | ESP,44,6342,6411,6615,7139,6633,6452,6852,7249,7199,7144,7292,7434,7350,6883,7287,7392,7244,7511,7794,7319,,7077.1,2020-11-02,0 46 | ESP,45,6742,6634,6682,7496,7067,6784,6726,7420,7054,6918,7299,7408,7366,7366,7333,7412,7775,7632,8012,7343,,7223.45,2020-11-09,0 47 | ESP,46,6795,7319,6790,7598,6892,7051,6935,7543,7529,7313,7354,7407,7422,7246,7604,7325,8076,8063,7999,7656,,7395.85,2020-11-16,0 48 | ESP,47,6949,7275,6699,7444,7338,7025,7254,7837,7403,7365,7531,7320,7308,7474,7628,7397,8090,8169,7932,7814,,7462.6,2020-11-23,0 49 | ESP,48,6833,7351,7133,7680,7389,7528,7044,7803,7527,7219,7752,7654,7333,8066,7729,7849,8321,8257,7929,7901,,7614.9,2020-11-30,0 50 | ESP,49,6624,7327,7222,7977,7513,7153,7248,7934,8102,7509,7782,7816,7747,8183,7645,8080,8124,8620,8051,7609,,7713.3,2020-12-07,0 51 | ESP,50,6779,7551,7453,8085,7537,7493,7593,7861,7938,7547,7681,8006,8137,8142,7990,8032,8612,9262,8312,7927,,7896.9,2020-12-14,0 52 | ESP,51,6969,8002,7497,8031,7837,7833,7909,8473,8205,7969,7917,8380,7866,8459,8245,8342,8980,9628,8427,7833,,8140.1,2020-12-21,0 53 | ESP,52,7206,8716,7438,8181,8296,7020,9754,8287,8713,8568,6020,9887,9173,8572,8535,8031,8407,11860,8650,7568,,8444.1,2020-12-28,0 54 | -------------------------------------------------------------------------------- /2020-05-28-excess-mortality/data/ger.csv: -------------------------------------------------------------------------------- 1 | Country,Week,2016,2017,2018,2019,2020,Average,Date,Baseline 2 | DEUTNP,1,18467,20918,19342,18628,18842,19338.75,2020-01-06,0 3 | DEUTNP,2,18439,22070,18770,19092,19389,19592.75,2020-01-13,0 4 | DEUTNP,3,18627,21236,19187,19046,19112,19524,2020-01-20,0 5 | DEUTNP,4,18707,22083,19171,19458,18888,19854.75,2020-01-27,0 6 | DEUTNP,5,18493,23640,19558,19774,19706,20366.25,2020-02-03,0 7 | DEUTNP,6,18541,22745,20086,19905,18931,20319.25,2020-02-10,0 8 | DEUTNP,7,18483,22683,21254,20125,19529,20636.25,2020-02-17,0 9 | DEUTNP,8,18475,22267,22888,20321,18837,20987.75,2020-02-24,0 10 | DEUTNP,9,18927,20930,25535,20737,19327,21532.25,2020-03-02,0 11 | DEUTNP,10,18888,19102,26777,20386,19471,21288.25,2020-03-09,0 12 | DEUTNP,11,18971,18665,24385,19738,19666,20439.75,2020-03-16,0 13 | DEUTNP,12,18826,17640,22777,18976,19492,19554.75,2020-03-23,0 14 | DEUTNP,13,18617,17731,20906,18501,19440,18938.75,2020-03-30,0 15 | DEUTNP,14,18245,17028,20038,18608,20295,18479.75,2020-04-06,0 16 | DEUTNP,15,17712,16901,19165,17794,20036,17893,2020-04-13,0 17 | DEUTNP,16,17536,16637,17992,18025,,17547.5,2020-04-20,0 18 | DEUTNP,17,17053,17634,17093,17849,,17407.25,2020-04-27,0 19 | DEUTNP,18,16901,17129,16789,17024,,16960.75,2020-05-04,0 20 | DEUTNP,19,17629,17343,17226,17059,,17314.25,2020-05-11,0 21 | DEUTNP,20,16601,17079,16488,17239,,16851.75,2020-05-18,0 22 | DEUTNP,21,16286,16451,16513,17068,,16579.5,2020-05-25,0 23 | DEUTNP,22,16346,16902,17039,16873,,16790,2020-06-01,0 24 | DEUTNP,23,15799,15846,16714,17426,,16446.25,2020-06-08,0 25 | DEUTNP,24,15717,16087,15582,16403,,15947.25,2020-06-15,0 26 | DEUTNP,25,16910,16819,15843,16581,,16538.25,2020-06-22,0 27 | DEUTNP,26,15699,16076,16569,17854,,16549.5,2020-06-29,0 28 | DEUTNP,27,16229,16424,16622,16489,,16441,2020-07-06,0 29 | DEUTNP,28,16172,15603,16070,16260,,16026.25,2020-07-13,0 30 | DEUTNP,29,16985,16589,16702,16779,,16763.75,2020-07-20,0 31 | DEUTNP,30,16157,16058,18340,19614,,17542.25,2020-07-27,0 32 | DEUTNP,31,15439,16494,20371,16974,,17319.5,2020-08-03,0 33 | DEUTNP,32,15487,15784,18478,16501,,16562.5,2020-08-10,0 34 | DEUTNP,33,16258,16149,16890,15918,,16303.75,2020-08-17,0 35 | DEUTNP,34,17147,15880,16612,16205,,16461,2020-08-24,0 36 | DEUTNP,35,16101,16064,16000,17601,,16441.5,2020-08-31,0 37 | DEUTNP,36,16116,15707,16390,15949,,16040.5,2020-09-07,0 38 | DEUTNP,37,16372,16147,16292,16235,,16261.5,2020-09-14,0 39 | DEUTNP,38,15606,16505,16651,16460,,16305.5,2020-09-21,0 40 | DEUTNP,39,16336,16747,15969,17361,,16603.25,2020-09-28,0 41 | DEUTNP,40,16352,16664,16622,16862,,16625,2020-10-05,0 42 | DEUTNP,41,17427,17470,16993,17615,,17376.25,2020-10-12,0 43 | DEUTNP,42,17599,17139,16552,17626,,17229,2020-10-19,0 44 | DEUTNP,43,17586,17059,16608,17229,,17120.5,2020-10-26,0 45 | DEUTNP,44,17580,16762,16895,17334,,17142.75,2020-11-02,0 46 | DEUTNP,45,17782,17371,17604,17708,,17616.25,2020-11-09,0 47 | DEUTNP,46,18591,17595,16842,18093,,17780.25,2020-11-16,0 48 | DEUTNP,47,17911,17677,17785,18445,,17954.5,2020-11-23,0 49 | DEUTNP,48,18147,17877,18091,18569,,18171,2020-11-30,0 50 | DEUTNP,49,18793,18295,18342,19280,,18677.5,2020-12-07,0 51 | DEUTNP,50,18885,18504,17943,19092,,18606,2020-12-14,0 52 | DEUTNP,51,19376,18502,18990,19046,,18978.5,2020-12-21,0 53 | DEUTNP,52,19744,18652,17954,18135,,18621.25,2020-12-28,0 54 | -------------------------------------------------------------------------------- /2020-05-28-excess-mortality/data/nyc.csv: -------------------------------------------------------------------------------- 1 | placename,week,2017,2018,2019,2020,average,date 2 | New York City,2,1178,1334,1071,1086,1194.3333333333333,2020-01-06 3 | New York City,3,1133,1163,1140,1130,1145.3333333333333,2020-01-13 4 | New York City,4,1185,1270,1119,1164,1191.3333333333333,2020-01-20 5 | New York City,5,1145,1168,1098,1145,1137,2020-01-27 6 | New York City,6,1146,1227,1226,1139,1199.6666666666667,2020-02-03 7 | New York City,7,1094,1187,1088,1119,1123,2020-02-10 8 | New York City,8,1061,1082,1066,1055,1069.6666666666667,2020-02-17 9 | New York City,9,1021,1086,1072,1095,1059.6666666666667,2020-02-24 10 | New York City,10,1051,1094,1082,1083,1075.6666666666667,2020-03-02 11 | New York City,11,1104,1068,1064,1120,1078.6666666666667,2020-03-09 12 | New York City,12,1059,1025,1009,1384,1031,2020-03-16 13 | New York City,13,974,1016,1093,2744,1027.6666666666667,2020-03-23 14 | New York City,14,990,1056,1025,6080,1023.6666666666666,2020-03-30 15 | New York City,15,1043,1076,1079,7741,1066,2020-04-06 16 | New York City,16,1012,1054,967,5747,1011,2020-04-13 17 | New York City,17,1031,957,946,3872,978,2020-04-20 18 | New York City,18,1015,984,999,2440,999.3333333333334,2020-04-27 19 | New York City,19,1002,909,1044,2286,985,2020-05-04 20 | New York City,20,1071,951,1044,1656,1022,2020-05-11 21 | New York City,21,995,1012,1044,,1017,2020-05-18 22 | New York City,22,971,976,893,,946.6666666666666,2020-05-25 23 | New York City,23,938,934,1033,,968.3333333333334,2020-06-01 24 | New York City,24,985,964,978,,975.6666666666666,2020-06-08 25 | New York City,25,988,1039,969,,998.6666666666666,2020-06-15 26 | New York City,26,950,975,985,,970,2020-06-22 27 | New York City,27,982,1036,977,,998.3333333333334,2020-06-29 28 | New York City,28,941,1006,960,,969,2020-07-06 29 | New York City,29,955,928,1016,,966.3333333333334,2020-07-13 30 | New York City,30,921,903,991,,938.3333333333334,2020-07-20 31 | New York City,31,962,920,1010,,964,2020-07-27 32 | New York City,32,964,963,958,,961.6666666666666,2020-08-03 33 | New York City,33,1006,983,970,,986.3333333333334,2020-08-10 34 | New York City,34,977,956,960,,964.3333333333334,2020-08-17 35 | New York City,35,969,944,933,,948.6666666666666,2020-08-24 36 | New York City,36,969,983,917,,956.3333333333334,2020-08-31 37 | New York City,37,1002,925,954,,960.3333333333334,2020-09-07 38 | New York City,38,948,991,1003,,980.6666666666666,2020-09-14 39 | New York City,39,1041,960,981,,994,2020-09-21 40 | New York City,40,1005,1047,1025,,1025.6666666666667,2020-09-28 41 | New York City,41,971,1050,1068,,1029.6666666666667,2020-10-05 42 | New York City,42,1002,1047,1045,,1031.3333333333333,2020-10-12 43 | New York City,43,1071,1091,1045,,1069,2020-10-19 44 | New York City,44,1016,1098,983,,1032.3333333333333,2020-10-26 45 | New York City,45,1049,1038,1091,,1059.3333333333333,2020-11-02 46 | New York City,46,1049,1048,1085,,1060.6666666666667,2020-11-09 47 | New York City,47,1030,1062,1044,,1045.3333333333333,2020-11-16 48 | New York City,48,1077,1084,1023,,1061.3333333333333,2020-11-23 49 | New York City,49,1014,1084,1137,,1078.3333333333333,2020-11-30 50 | New York City,50,1107,1037,1122,,1088.6666666666667,2020-12-07 51 | New York City,51,1126,1102,1098,,1108.6666666666667,2020-12-14 52 | -------------------------------------------------------------------------------- /2020-05-28-excess-mortality/data/swe.csv: -------------------------------------------------------------------------------- 1 | Country,Week,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,2020,Average,Date,Baseline 2 | SWE,1,2081,2192,1910,1962,1840,1927,1914,2012,1998,1943,1818,1977.9,2020-01-06,0 3 | SWE,2,1899,2010,1953,1968,1787,1966,1860,2149,1941,1820,1890,1935.3,2020-01-13,0 4 | SWE,3,1942,1953,1919,1999,1846,1935,1914,2122,1945,1839,1827,1941.4,2020-01-20,0 5 | SWE,4,1865,1867,1876,1945,1758,1946,1958,2060,1928,1828,1727,1903.1,2020-01-27,0 6 | SWE,5,1919,1841,1840,1986,1864,1975,2006,1910,1854,1812,1846,1900.7,2020-02-03,0 7 | SWE,6,1848,1830,1874,2024,1887,1868,1909,1883,1983,1882,1727,1898.8,2020-02-10,0 8 | SWE,7,1836,1761,1931,1879,1894,2001,1837,1881,2024,1764,1819,1880.8,2020-02-17,0 9 | SWE,8,1786,1784,2082,1971,1784,2107,1838,2010,2116,1820,1774,1929.8,2020-02-24,0 10 | SWE,9,1813,1862,2060,2090,1792,2076,1845,2069,2187,1772,1776,1956.6,2020-03-02,0 11 | SWE,10,1874,1902,2125,1934,1746,2041,1861,1989,2204,1690,1823,1936.6,2020-03-09,0 12 | SWE,11,1844,1882,2037,1883,1693,1932,1810,1830,2089,1829,1724,1882.9,2020-03-16,0 13 | SWE,12,1741,1785,2010,1909,1796,1874,1800,1849,1997,1632,1858,1839.3,2020-03-23,0 14 | SWE,13,1814,1779,1890,1870,1638,1930,1795,1692,1948,1665,2029,1802.1,2020-03-30,0 15 | SWE,14,1754,1823,1819,1911,1758,1834,1778,1782,1988,1698,2369,1814.5,2020-04-06,0 16 | SWE,15,1731,1757,1811,1876,1652,1849,1705,1794,1782,1612,2554,1756.9,2020-04-13,0 17 | SWE,16,1749,1748,1907,1812,1700,1844,1773,1719,1687,1736,2493,1767.5,2020-04-20,0 18 | SWE,17,1745,1758,1738,1803,1644,1764,1771,1768,1639,1698,2218,1732.8,2020-04-27,0 19 | SWE,18,1720,1657,1725,1735,1675,1656,1604,1772,1661,1613,,1681.8,2020-05-04,0 20 | SWE,19,1695,1673,1627,1682,1742,1661,1619,1696,1572,1643,,1661,2020-05-11,0 21 | SWE,20,1647,1681,1727,1570,1635,1668,1586,1724,1486,1557,,1628.1,2020-05-18,0 22 | SWE,21,1620,1636,1740,1576,1651,1670,1565,1584,1460,1486,,1598.8,2020-05-25,0 23 | SWE,22,1615,1617,1621,1544,1549,1627,1550,1646,1481,1541,,1579.1,2020-06-01,0 24 | SWE,23,1588,1577,1659,1536,1565,1617,1541,1620,1513,1544,,1576,2020-06-08,0 25 | SWE,24,1574,1587,1515,1535,1546,1609,1462,1549,1441,1444,,1526.2,2020-06-15,0 26 | SWE,25,1571,1552,1528,1659,1610,1592,1541,1590,1500,1526,,1566.9,2020-06-22,0 27 | SWE,26,1615,1523,1622,1595,1638,1525,1573,1491,1633,1512,,1572.7,2020-06-29,0 28 | SWE,27,1644,1570,1599,1633,1580,1674,1541,1587,1588,1537,,1595.3,2020-07-06,0 29 | SWE,28,1635,1620,1639,1504,1692,1560,1549,1549,1585,1558,,1589.1,2020-07-13,0 30 | SWE,29,1682,1566,1592,1570,1610,1529,1605,1525,1724,1482,,1588.5,2020-07-20,0 31 | SWE,30,1602,1679,1551,1552,1674,1538,1616,1512,1642,1514,,1588,2020-07-27,0 32 | SWE,31,1600,1605,1625,1499,1659,1588,1630,1484,1723,1491,,1590.4,2020-08-03,0 33 | SWE,32,1583,1567,1635,1573,1607,1524,1574,1536,1450,1548,,1559.7,2020-08-10,0 34 | SWE,33,1573,1508,1613,1508,1590,1535,1574,1552,1505,1486,,1544.4,2020-08-17,0 35 | SWE,34,1506,1629,1586,1553,1612,1563,1567,1545,1495,1542,,1559.8,2020-08-24,0 36 | SWE,35,1569,1621,1559,1598,1668,1458,1567,1527,1584,1642,,1579.3,2020-08-31,0 37 | SWE,36,1647,1581,1593,1611,1691,1648,1686,1568,1617,1441,,1608.3,2020-09-07,0 38 | SWE,37,1614,1605,1609,1614,1500,1552,1556,1596,1516,1559,,1572.1,2020-09-14,0 39 | SWE,38,1717,1562,1527,1580,1630,1566,1536,1590,1645,1540,,1589.3,2020-09-21,0 40 | SWE,39,1652,1745,1642,1576,1639,1633,1531,1562,1553,1648,,1618.1,2020-09-28,0 41 | SWE,40,1628,1723,1688,1612,1683,1651,1601,1532,1606,1638,,1636.2,2020-10-05,0 42 | SWE,41,1594,1723,1710,1547,1675,1528,1598,1708,1715,1654,,1645.2,2020-10-12,0 43 | SWE,42,1755,1692,1667,1700,1687,1574,1662,1695,1542,1622,,1659.6,2020-10-19,0 44 | SWE,43,1696,1698,1652,1686,1678,1698,1750,1648,1660,1724,,1689,2020-10-26,0 45 | SWE,44,1694,1744,1692,1613,1671,1658,1626,1644,1706,1638,,1668.6,2020-11-02,0 46 | SWE,45,1640,1652,1728,1654,1669,1652,1718,1757,1640,1698,,1680.8,2020-11-09,0 47 | SWE,46,1791,1709,1683,1600,1765,1710,1717,1608,1541,1674,,1679.8,2020-11-16,0 48 | SWE,47,1719,1650,1667,1683,1622,1678,1771,1753,1534,1712,,1678.9,2020-11-23,0 49 | SWE,48,1750,1659,1693,1800,1678,1691,1702,1700,1780,1688,,1714.1,2020-11-30,0 50 | SWE,49,1862,1728,1718,1799,1663,1805,1790,1740,1787,1731,,1762.3,2020-12-07,0 51 | SWE,50,1849,1849,1767,1742,1796,1669,1842,1765,1720,1719,,1771.8,2020-12-14,0 52 | SWE,51,1842,1848,1962,1725,1826,1753,1858,1797,1741,1826,,1817.8,2020-12-21,0 53 | SWE,52,2002,1839,1912,1888,1923,1737,1868,1815,1758,1718,,1846,2020-12-28,0 54 | -------------------------------------------------------------------------------- /2020-05-28-excess-mortality/data/usa.csv: -------------------------------------------------------------------------------- 1 | Country,Week,2013,2014,2015,2016,2017,2018,2019,2020,Average,Date,Baseline 2 | USA,1,59430,53269,59335,55784,59760,66129,58290,59441,58856.71428571428,2020-01-06,0 3 | USA,2,60790,55617,61731,55523,60975,67491,58347,59725,60067.71428571428,2020-01-13,0 4 | USA,3,59159,54569,61135,55178,59286,64641,58189,58227,58879.57142857143,2020-01-20,0 5 | USA,4,57843,54077,58622,55602,58045,62777,57830,57647,57828,2020-01-27,0 6 | USA,5,56345,53950,57264,54891,58427,60972,58125,57117,57139.142857142855,2020-02-03,0 7 | USA,6,55683,53387,57277,55103,59037,61107,58489,57489,57154.71428571428,2020-02-10,0 8 | USA,7,54418,53805,56413,55781,58474,59774,57914,56748,56654.142857142855,2020-02-17,0 9 | USA,8,53468,52634,56342,54862,58283,57790,57857,56643,55890.857142857145,2020-02-24,0 10 | USA,9,53049,51669,55659,55871,57250,56690,57917,56694,55443.57142857143,2020-03-02,0 11 | USA,10,53332,52052,55724,56106,57469,57089,58497,56030,55752.71428571428,2020-03-09,0 12 | USA,11,53016,51774,55262,54452,56650,56317,57895,53789,55052.28571428572,2020-03-16,0 13 | USA,12,52068,51381,54253,54660,57041,55758,57084,53808,54606.42857142857,2020-03-23,0 14 | USA,13,51788,50848,53229,53879,55697,54913,56669,57144,53860.42857142857,2020-03-30,0 15 | USA,14,51322,50740,52999,54059,55153,55285,56593,63799,53735.857142857145,2020-04-06,0 16 | USA,15,50842,50520,52690,53484,54858,55223,55477,65519,53299.142857142855,2020-04-13,0 17 | USA,16,49531,49732,52839,53144,53067,54031,54454,52518,52399.71428571428,2020-04-20,0 18 | USA,17,48348,49741,51603,51020,53289,53719,53646,,51623.71428571428,2020-04-27,0 19 | USA,18,48353,49587,51457,51266,52654,53734,53972,,51574.71428571428,2020-05-04,0 20 | USA,19,47909,50314,51651,50992,51981,52101,53458,,51200.857142857145,2020-05-11,0 21 | USA,20,47334,47925,50667,50461,52476,50617,53548,,50432.57142857143,2020-05-18,0 22 | USA,21,47283,48592,49324,50487,50967,50923,53668,,50177.71428571428,2020-05-25,0 23 | USA,22,46585,48154,49713,49706,51248,51037,52710,,49879,2020-06-01,0 24 | USA,23,46966,47743,49033,49914,51412,51998,53126,,50027.42857142857,2020-06-08,0 25 | USA,24,46523,47710,49743,49906,50790,51383,52626,,49811.57142857143,2020-06-15,0 26 | USA,25,46442,47529,49101,49617,51192,51043,52266,,49598.57142857143,2020-06-22,0 27 | USA,26,46370,47334,49053,49743,50611,50851,52182,,49449.142857142855,2020-06-29,0 28 | USA,27,46628,47234,49207,49695,50957,51681,52324,,49675.142857142855,2020-07-06,0 29 | USA,28,45762,47284,48908,49632,49972,51188,51912,,49236.857142857145,2020-07-13,0 30 | USA,29,46127,47085,49220,49266,50120,50604,51617,,49148.42857142857,2020-07-20,0 31 | USA,30,46170,47114,48538,49690,49360,50267,51616,,48965,2020-07-27,0 32 | USA,31,46137,46928,48256,49501,50084,50633,51357,,48985.142857142855,2020-08-03,0 33 | USA,32,46001,46876,47728,49734,50232,50963,51653,,49026.71428571428,2020-08-10,0 34 | USA,33,45822,46633,47972,49806,50184,50295,50934,,48806.57142857143,2020-08-17,0 35 | USA,34,45999,46623,48430,49502,49514,50453,50966,,48783.857142857145,2020-08-24,0 36 | USA,35,46265,46388,48487,49573,50824,50600,51106,,49034.71428571428,2020-08-31,0 37 | USA,36,45572,47284,48714,50066,50973,50292,51772,,49239,2020-09-07,0 38 | USA,37,46183,46804,48758,49907,51692,51081,51547,,49424.57142857143,2020-09-14,0 39 | USA,38,46550,47930,48851,49871,51226,51576,51677,,49668.71428571428,2020-09-21,0 40 | USA,39,46651,48403,49222,50248,51339,50951,52680,,49927.71428571428,2020-09-28,0 41 | USA,40,47484,48352,48802,51394,52102,52348,52469,,50421.57142857143,2020-10-05,0 42 | USA,41,47294,49338,50947,52120,51571,51846,52880,,50856.57142857143,2020-10-12,0 43 | USA,42,47597,49218,49829,51434,52215,52971,54151,,51059.28571428572,2020-10-19,0 44 | USA,43,47734,49038,50658,51860,52537,53757,53927,,51358.71428571428,2020-10-26,0 45 | USA,44,48773,48935,50378,51734,53663,53632,54006,,51588.71428571428,2020-11-02,0 46 | USA,45,48934,50944,51154,52516,53233,53558,55511,,52264.28571428572,2020-11-09,0 47 | USA,46,49395,50355,50666,53432,53762,54694,55730,,52576.28571428572,2020-11-16,0 48 | USA,47,49584,52466,51383,53120,54117,54844,56058,,53081.71428571428,2020-11-23,0 49 | USA,48,49278,51755,51193,54492,54757,55055,55283,,53116.142857142855,2020-11-30,0 50 | USA,49,50807,52721,51989,55125,55590,55962,57068,,54180.28571428572,2020-12-07,0 51 | USA,50,51842,53541,53549,55973,57363,56380,57382,,55147.142857142855,2020-12-14,0 52 | USA,51,52538,54617,51835,56686,59500,56523,57120,,55545.57142857143,2020-12-21,0 53 | USA,52,51940,56021,52756,57603,61084,56024,58140,,56224,2020-12-28,0 54 | -------------------------------------------------------------------------------- /2020-05-28-excess-mortality/esp-excess-mortality.R: -------------------------------------------------------------------------------- 1 | needs(tidyverse) 2 | needs(readxl) 3 | 4 | raw_data <- read_excel("2020-05-26_stmf_raw.xlsx", sheet = "ESP", col_types = c("text", 5 | "numeric", "numeric", "text", "numeric", 6 | "numeric", "numeric", "numeric", 7 | "numeric", "numeric", "skip", "skip", 8 | "skip", "skip", "skip", "skip", "numeric", 9 | "numeric", "numeric"), skip = 2) 10 | 11 | past_years <- c(as.character(2000:2019)) 12 | 13 | output <- raw_data %>% 14 | filter(Sex == "b") %>% # do not differentiate by gender 15 | head(-1) %>% # remove last week, which may be incomplete 16 | select(Country, Year, Week, Total) %>% # select relevant columns 17 | pivot_wider(names_from = Year, values_from = Total) %>% # pivot to wide table 18 | mutate( 19 | Average = rowMeans(select(., past_years)), # calculate mean 20 | Date = as.Date(paste(2020, Week, 1, sep="-"), "%Y-%U-%u"), 21 | Baseline = 0 22 | ) 23 | 24 | View(output) 25 | 26 | output %>% write_csv('data/esp.csv', na = '') -------------------------------------------------------------------------------- /2020-05-28-excess-mortality/ger-excess-mortality.R: -------------------------------------------------------------------------------- 1 | needs(tidyverse) 2 | needs(readxl) 3 | 4 | raw_data <- read_excel("2020-05-26_stmf_raw.xlsx", sheet = "DEUTNP", col_types = c("text", 5 | "numeric", "numeric", "text", "numeric", 6 | "numeric", "numeric", "numeric", 7 | "numeric", "numeric", "skip", "skip", 8 | "skip", "skip", "skip", "skip", "numeric", 9 | "numeric", "numeric"), skip = 2) 10 | 11 | past_years <- c(as.character(2016:2019)) 12 | 13 | output <- raw_data %>% 14 | filter(Sex == "b") %>% # do not differentiate by gender 15 | head(-1) %>% # remove last week, which may be incomplete 16 | select(Country, Year, Week, Total) %>% # select relevant columns 17 | pivot_wider(names_from = Year, values_from = Total) %>% # pivot to wide table 18 | mutate( 19 | Average = rowMeans(select(., past_years)), # calculate mean 20 | Date = as.Date(paste(2020, Week, 1, sep="-"), "%Y-%U-%u"), 21 | Baseline = 0 22 | ) 23 | 24 | View(output) 25 | 26 | output %>% write_csv('data/ger.csv', na = '') -------------------------------------------------------------------------------- /2020-05-28-excess-mortality/nyc-excess-mortality.R: -------------------------------------------------------------------------------- 1 | needs(tidyverse) 2 | 3 | mortality <- read_csv("https://raw.githubusercontent.com/nytimes/covid-19-data/master/excess-deaths/deaths.csv", 4 | col_types = cols(baseline = col_double(), 5 | excess_deaths = col_double(), expected_deaths = col_double(), 6 | placename = col_character())) 7 | 8 | past_years <- c("2017", "2018", "2019") 9 | 10 | output <- mortality %>% 11 | filter(placename == "New York City") %>% 12 | select(placename, year, week, deaths) %>% # select relevant columns 13 | pivot_wider(names_from = year, values_from = deaths) %>% 14 | mutate( 15 | average = rowMeans(select(., past_years)), # calculate mean 16 | date = as.Date(paste(2020, week-1, 1, sep="-"), "%Y-%U-%u") 17 | ) 18 | 19 | View(output) 20 | 21 | output %>% write_csv('data/nyc.csv', na = '') 22 | -------------------------------------------------------------------------------- /2020-05-28-excess-mortality/swe-excess-mortality.R: -------------------------------------------------------------------------------- 1 | needs(tidyverse) 2 | needs(readxl) 3 | 4 | raw_data <- read_excel("2020-05-26_stmf_raw.xlsx", sheet = "SWE", col_types = c("text", 5 | "numeric", "numeric", "text", "numeric", 6 | "numeric", "numeric", "numeric", 7 | "numeric", "numeric", "skip", "skip", 8 | "skip", "skip", "skip", "skip", "numeric", 9 | "numeric", "numeric"), skip = 2) 10 | 11 | past_years <- c(as.character(2010:2019)) 12 | 13 | output <- raw_data %>% 14 | filter(Sex == "b") %>% # do not differentiate by gender 15 | head(-1) %>% # remove last week, which may be incomplete 16 | select(Country, Year, Week, Total) %>% # select relevant columns 17 | pivot_wider(names_from = Year, values_from = Total) %>% # pivot to wide table 18 | mutate( 19 | Average = rowMeans(select(., past_years)), # calculate mean 20 | Date = as.Date(paste(2020, Week, 1, sep="-"), "%Y-%U-%u"), 21 | Baseline = 0 22 | ) 23 | 24 | View(output) 25 | 26 | output %>% write_csv('data/swe.csv', na = '') 27 | -------------------------------------------------------------------------------- /2020-05-28-excess-mortality/usa-excess-mortality.R: -------------------------------------------------------------------------------- 1 | needs(tidyverse) 2 | needs(readxl) 3 | 4 | raw_data <- read_excel("2020-05-26_stmf_raw.xlsx", sheet = "USA", col_types = c("text", 5 | "numeric", "numeric", "text", "numeric", 6 | "numeric", "numeric", "numeric", 7 | "numeric", "numeric", "skip", "skip", 8 | "skip", "skip", "skip", "skip", "numeric", 9 | "numeric", "numeric"), skip = 2) 10 | 11 | past_years <- c(as.character(2013:2019)) 12 | 13 | output <- raw_data %>% 14 | filter(Sex == "b") %>% # do not differentiate by gender 15 | head(-1) %>% # remove last week, which may be incomplete 16 | select(Country, Year, Week, Total) %>% # select relevant columns 17 | pivot_wider(names_from = Year, values_from = Total) %>% # pivot to wide table 18 | mutate( 19 | Average = rowMeans(select(., past_years)), # calculate mean 20 | Date = as.Date(paste(2020, Week, 1, sep="-"), "%Y-%U-%u"), 21 | Baseline = 0 22 | ) 23 | 24 | View(output) 25 | 26 | output %>% write_csv('data/usa.csv', na = '') -------------------------------------------------------------------------------- /2020-09-10-ridgeline-plot/README.md: -------------------------------------------------------------------------------- 1 | # Ridgeline plot: Unknown Pleasures by Joy Division 2 | 3 | This is a node.js script to process data to recreate the album cover of *Unknown Pleasures* by Joy Division in Datawrapper. 4 | 5 | ![Ridgeline plot: Unknown Pleasures by Joy Division](https://img.datawrapper.de/UR2uC/full.png) 6 | 7 | ### Related links 8 | 9 | * [Weekly chart article](https://blog.datawrapper.de/weekly-ridgeline-plot/) 10 | 11 | ### Notes 12 | 13 | You need to have [node.js](https://nodejs.org/en/) installed on your system in order to run this script. Execute the script by running `node script.js`. 14 | -------------------------------------------------------------------------------- /2020-09-10-ridgeline-plot/script.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | 3 | // using `4` here so that end result looks close to the original artwork when chart is a square 4 | const VERTICAL_GAP = 4; 5 | 6 | fs.readFile('./pulsar_sorted.csv', 'utf8', (err, data) => { 7 | let csvText = ''; 8 | const transformRows = []; 9 | const rows = data.split('\n'); 10 | rows.forEach((row, rowIndex) => { 11 | transformValues = []; 12 | const values = row.split(','); 13 | values.forEach((value) => { 14 | // here we add increasing vertical distance to each new row 15 | const add = !rowIndex ? 0 : rowIndex * VERTICAL_GAP; 16 | // we use `Math.max(x, 0)` to ensure no negative values 17 | const newValue = Math.max(+value + add, 0); 18 | transformValues.push(+newValue.toFixed(2)); 19 | }); 20 | transformRows.push(transformValues); 21 | }); 22 | 23 | let currentHighest = []; 24 | transformRows.forEach((row, rowIndex) => { 25 | const values = []; 26 | // populate `currentHighest` with values from first row if empty 27 | if (!currentHighest.length) currentHighest = row; 28 | currentHighest = currentHighest.map((value, i) => { 29 | // find the higher value between currently saved highest and row 30 | const maxValue = Math.max(value, row[i]); 31 | values.push(maxValue); 32 | // save this value to `currentHighest` array 33 | return maxValue; 34 | }); 35 | 36 | csvText += `${values.join(',')}\n`; 37 | }); 38 | 39 | // add one more row to fill the background to the top (+ add some padding) 40 | const highestValue = Math.max(...currentHighest) + 10; 41 | const topAreaRow = currentHighest.map((value) => highestValue); 42 | csvText += `${topAreaRow.join(',')}\n`; 43 | 44 | fs.writeFile('./output.csv', csvText, (err) => { 45 | if (err) throw err; 46 | }); 47 | }); 48 | -------------------------------------------------------------------------------- /2020-10-18-trump-tweet-heatmap/.env-template: -------------------------------------------------------------------------------- 1 | API_TOKEN= -------------------------------------------------------------------------------- /2020-10-18-trump-tweet-heatmap/README.md: -------------------------------------------------------------------------------- 1 | # Create a Datawrapper scatterplot heatmap of @realDonaldTrump's tweets 2 | 3 | This is a collection of node.js scripts for pulling data from the [Trump Twitter Archive](https://trumptwitterarchive.com), and creating the following chart, which was published on the Datawrapper Blog as a Weekly Chart ([here](https://blog.datawrapper.de/weekly-chart-trump-tweet-heatmap/) for the original article) 4 | 5 | Heatmap 6 | 7 | ### Prerequisites 8 | 9 | You need to have [node.js](https://nodejs.org/en/) and [npm](https://www.npmjs.com/) installed on your system in order to run these scripts. 10 | 11 | ### How to use these scripts 12 | 13 | To download the data and create your own version of this chart, you'll need to: 14 | 15 | **1. Install required packages by running:** 16 | ``` 17 | npm install 18 | ``` 19 | 20 | **2. Configure API Token** 21 | 22 | - Make a copy of the .env-template file, and add your Datawrapper API Token, so that it looks something like this: 23 | 24 | ``` 25 | API_TOKEN=XXXXXXXXXXXXXXXXXXXXXXXXXX 26 | ``` 27 | 28 | - Then save the file with the name `.env`. 29 | 30 | (If you don't have an API token, you can read up on how to set one up [here](https://developer.datawrapper.de/docs)) 31 | 32 | **2. To pull the latest data and create a chart, run:** 33 | 34 | ``` 35 | npm run all 36 | ``` 37 | 38 | (If you want to update the data in an existing chart, do `npm run all` with your chart ID afterwards) 39 | 40 | **This will:** 41 | 42 | 1. Pull the latest data from [Trump Twitter Archive](https://trumptwitterarchive.com) 43 | 2. Collect and save some stats 44 | 3. Summarise the tweets into daily data 45 | 3. Generate the CSV for your chart 46 | 4. Create (or update) your Datawrapper chart 47 | 48 | ### The individual scripts 49 | 50 | You can also run individual scripts, instead of all of them: 51 | 52 | - [get-tweets](https://github.com/datawrapper/snippets/blob/master/2020-10-18-trump-tweet-heatmap/get-tweets.js) Will download the latest tweets, and add them to the `all-tweets.json` file. 53 | - [get-stats](https://github.com/datawrapper/snippets/blob/master/2020-10-18-trump-tweet-heatmap/get-stats.js) Will extract some key information on use of certain words, total number of tweets, etc. And save this information to the `tweet-stats.json` file. 54 | - [count-tweets](https://github.com/datawrapper/snippets/blob/master/2020-10-18-trump-tweet-heatmap/count-tweets.js) Will get the daily tweet totals, pulling from the `all-tweets.json` file. This will also get the information about the most popular tweet of that each day. This gets saved to the file `daily-tweets.json` 55 | - [create-heatmap](https://github.com/datawrapper/snippets/blob/master/2020-10-18-trump-tweet-heatmap/create-heatmap.js) This will create a Datawrapper heatmap like the image above out of the data in your `daily-tweets.js` file. (it also saves the CSV to `chart-data.csv`) 56 | 57 | Run any of these scripts with `node script-name.js`. 58 | -------------------------------------------------------------------------------- /2020-10-18-trump-tweet-heatmap/count-tweets.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const moment = require('moment'); 3 | const chalk = require('chalk'); 4 | 5 | const { getLetters } = require('./utils/utils'); 6 | 7 | let tweetData = JSON.parse(fs.readFileSync('./data/all-tweets.json')); 8 | 9 | console.log(chalk.grey('Processing tweet data...')); 10 | 11 | const dailyTweets = {}; 12 | 13 | const startDate = moment('2017-01-01'); 14 | const endDate = moment(new Date(tweetData[tweetData.length - 1].created_at)); 15 | const totalDays = endDate.diff(startDate,'days') + 1; 16 | 17 | for (let i = 0; i < totalDays; i++) { 18 | const date = startDate.format('YYYY-M-D').split('-').map(d => +d); 19 | const tweets = tweetData.filter(tweet => { 20 | return tweet.year === date[0] && tweet.month === date[1] && tweet.day === date[2]; 21 | }); 22 | const retweets = tweets.filter(tweet => tweet.is_retweet).length; 23 | const highestLikes = Math.max(...tweets.map(t => t.favorite_count)); 24 | const highestRetweets = Math.max(...tweets.map(t => t.retweet_count)); 25 | 26 | const totalLikes = tweets.reduce((acc,tweet) => { 27 | acc += tweet.favorite_count; 28 | return acc; 29 | },0); 30 | const totalRetweets = tweets.reduce((acc,tweet) => { 31 | acc += tweet.retweet_count; 32 | return acc; 33 | },0); 34 | 35 | const letters = getLetters(tweets,'[a-zA-Z]'); 36 | const capitalLetters = getLetters(tweets,'[A-Z]'); 37 | const mostPopular = tweets.length ? tweets.filter(t => t.favorite_count === highestLikes)[0] : false; 38 | const mostRetweeted = tweets.length ? tweets.filter(t => t.retweet_count === highestRetweets)[0] : false; 39 | 40 | const data = { 41 | total: tweets.length, 42 | retweets: retweets, 43 | original: tweets.length - retweets, 44 | highestLikes, 45 | highestRetweets, 46 | totalLikes, 47 | letters, 48 | capitalLetters, 49 | loudness: 100*capitalLetters/letters, 50 | likeRate:totalLikes/tweets.length, 51 | totalRetweets, 52 | retweetRate:totalRetweets/tweets.length, 53 | mostPopular: { 54 | text: mostPopular ? mostPopular.text : '', 55 | id: mostPopular ? mostPopular.id_str : '', 56 | date: moment(new Date(mostPopular ? mostPopular.created_at : startDate)).format('YYYY-MM-DD hh:mm') 57 | }, 58 | mostRetweeted: { 59 | text: mostRetweeted ? mostRetweeted.text : '', 60 | id: mostRetweeted ? mostRetweeted.id_str : '', 61 | date: moment(new Date(mostRetweeted ? mostRetweeted.created_at : startDate)).format('YYYY-MM-DD hh:mm') 62 | } 63 | }; 64 | 65 | const yearMonth = [date[0],date[1]].join('-'); 66 | 67 | if (!dailyTweets[yearMonth]) dailyTweets[yearMonth] = {}; 68 | 69 | dailyTweets[yearMonth][date[2]] = data; 70 | startDate.add(1,'day'); 71 | } 72 | 73 | fs.writeFileSync('./data/daily-tweets.json', JSON.stringify(dailyTweets, null, '\t')) 74 | console.log(chalk.green('Summarised tweets and saved to daily-tweets.json')); 75 | 76 | -------------------------------------------------------------------------------- /2020-10-18-trump-tweet-heatmap/create-heatmap.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const chalk = require('chalk'); 3 | const { argv } = require('yargs'); 4 | 5 | const { interpolateLab } =require('d3-interpolate'); 6 | const { scaleLinear } =require('d3-scale'); 7 | const { color } =require('d3-color'); 8 | 9 | const { createChart, publishChart } = require('./utils/dw-api-utils'); 10 | const { getMax, tooltip, notes, annotations, hlRange } = require('./utils/utils'); 11 | 12 | const dailyTweets = JSON.parse(fs.readFileSync('./data/daily-tweets.json')); 13 | 14 | const allData = []; 15 | const toPlot = 'total'; 16 | let valueMax; 17 | 18 | const defaultColors = ['#ffffff', '#bee4fb', '#7ec9f8', '#3daef4', '#1996e6', '#1180cd', '#0869b4', '#00539b']; 19 | 20 | const updateChart = argv.id; 21 | const colors = argv.colors ? argv.colors.split(',') : defaultColors; 22 | 23 | if (['metadata','data'].includes(argv.update) && !argv.id) { 24 | console.log(chalk.yellow(`make sure to specify id of chart you want to update the ${argv.update} for`)); 25 | return; 26 | } 27 | 28 | const colorCount = colors.length; 29 | 30 | const props = Object.keys(dailyTweets['2017-1']['1']).filter(prop => isFinite(dailyTweets['2017-1']['1'][prop])); 31 | const mostPopularProps = Object.keys(dailyTweets['2017-1']['1'].mostPopular); 32 | 33 | 34 | 35 | /*============ Prepare Gradients ============*/ 36 | const gradients = props.reduce((acc,prop) => { 37 | const max = getMax(prop,dailyTweets); 38 | if (prop === toPlot) valueMax = max; 39 | 40 | const domain = [...Array(colors.length + 1).keys()] 41 | .map(i => i*(max/colors.length)); 42 | 43 | acc[prop] = scaleLinear() 44 | .domain(domain) 45 | .range(colors) 46 | .interpolate(interpolateLab); 47 | return acc; 48 | },{}); 49 | /*========================================*/ 50 | 51 | 52 | 53 | /*========== Construct table header ======*/ 54 | const header = ['month','day']; 55 | props.forEach(prop => { 56 | header.push(prop) 57 | header.push(prop+'-color'); 58 | header.concat(['most-popular-text','most-popular-id']) 59 | }); 60 | mostPopularProps.forEach(prop => { 61 | header.push('most-popular-'+prop); 62 | }) 63 | 64 | allData.push(header); 65 | /*========================================*/ 66 | 67 | 68 | 69 | 70 | /*============ Prepare Dataset ============*/ 71 | console.log(chalk.grey('Constructing csv dataset...')); 72 | 73 | const customColors = {}; 74 | 75 | Object.keys(dailyTweets).forEach(yearMonth => { 76 | Object.keys(dailyTweets[yearMonth]).forEach(day => { 77 | const tweet = dailyTweets[yearMonth][day]; 78 | const rowData = []; 79 | const split = yearMonth.split('-'); 80 | const date = `${split[0]}-${split[1] < 10 ? ('0' + split[1]) : split[1]}-01`; 81 | 82 | rowData.push(date); 83 | rowData.push(day); 84 | props.forEach(prop => { 85 | const val = tweet[prop]; 86 | const c = color(gradients[prop](val)).formatHex(); 87 | rowData.push(val); 88 | rowData.push(c); 89 | if (!customColors[c]) { 90 | customColors[c] = c; 91 | } 92 | }); 93 | mostPopularProps.forEach(prop => { 94 | let val = tweet.mostPopular[prop]; 95 | if (prop === 'text') { 96 | val = '"'+val.replace(/,/gm,",").replace(/"/gm,'"')+'"'; 97 | } 98 | rowData.push(val) 99 | }); 100 | allData.push(rowData); 101 | }); 102 | }) 103 | /*========================================*/ 104 | 105 | 106 | 107 | 108 | /*============ Array to CSV ==============*/ 109 | const csv = allData.map(row => row.join(',')).join('\n'); 110 | /*========================================*/ 111 | 112 | 113 | 114 | 115 | 116 | /*============ Save CSV file ==============*/ 117 | fs.writeFileSync('./data/chart-data.csv', csv); 118 | console.log(chalk.green('Saved dataset to chart-data.csv')); 119 | /*=========================================*/ 120 | 121 | 122 | 123 | 124 | /*======== Define chart metadata ==========*/ 125 | const metadata = { 126 | title: `In the past year, @realDonaldTrump has broken all his tweet records`, 127 | type:'d3-scatter-plot', 128 | theme:'datawrapper', 129 | metadata: { 130 | "describe":{ 131 | "intro":"@realDonaldTrump tweets from 2017 until today", 132 | "byline":"Elana Levin Schtulberg / Datawrapper", 133 | "source-name":"Trump Twitter Archive", 134 | "source-url":"http://www.trumptwitterarchive.com/" 135 | }, 136 | data: { 137 | changes:[{"row":0,"time":1602425700285,"value":"","column":0,"ignored":false,"previous":"month"}], 138 | 'column-format':{ 139 | 'most-popular-id':{ 140 | 'type':'text' 141 | } 142 | } 143 | }, 144 | visualize: { 145 | "shape": "fixed", 146 | "size": "fixed", 147 | "fixed-symbol": "symbolSquare", 148 | "fixed-size": "16.7", 149 | "color-base": 0, 150 | "auto-labels": false, 151 | "show-color-key": false, 152 | "outlines": false, 153 | "tooltip":tooltip, 154 | "custom-colors":customColors, 155 | "text-annotations":annotations, 156 | "highlight-range":hlRange, 157 | "show-tooltips": true, 158 | 'sticky-tooltips': true, 159 | "y-grid-lines": "just-labels", 160 | "y-format": "MMM", 161 | "y-axis": { 162 | "range":["01-2021","11-2016"], 163 | "ticks":[] 164 | }, 165 | "x-axis":{ 166 | "range": [0,34], 167 | "ticks": [1,3,5,7,9,11,13,15,17,19,21,23,25,27,29,31] 168 | }, 169 | "x-grid-lines": "just-labels", 170 | "x-pos": "zero" 171 | }, 172 | "annotate":{ 173 | "notes":notes(colors,94,15,valueMax) 174 | }, 175 | "axes": { 176 | "x": "day", 177 | "y": "month", 178 | "color": toPlot+'-color' 179 | }, 180 | "publish":{ 181 | "embed-width": 640, 182 | "embed-height": 1105, 183 | "text": "#333333", 184 | "background": "#ffffff", 185 | "chart-height": 845 186 | } 187 | } 188 | }; 189 | /*=========================================*/ 190 | 191 | 192 | 193 | /*============= Create Chart ==============*/ 194 | console.log(chalk.grey('Creating new chart...')); 195 | 196 | createChart({metadata,data:csv, id:updateChart, update:argv.update}).then(res => { 197 | if (!res.error) { 198 | const chartId = updateChart || res.id; 199 | console.log(chalk.green(`Finished ${updateChart ? 'updating' : 'creating'} chart with id ${chartId}`)); 200 | console.log(chalk.bgBlue(`Check out your chart at https://app.datawrapper.de/chart/${chartId}/visualize`)); 201 | if (argv.publish) { 202 | console.log(chalk.grey(`Publishing ${chartId}...`)); 203 | publishChart(chartId).then(res =>{ 204 | console.log(chalk.green(`Published ${chartId}`)); 205 | }).catch(err => { 206 | console.log(chalk.red(`Failed to publish ${updateChart || res.id}`)); 207 | }) 208 | } 209 | } else { 210 | console.log(chalk.red(`Failed while trying to ${res.failedAt}`)); 211 | console.log(res.error); 212 | } 213 | }) 214 | .catch(err => { 215 | console.log(chalk.red(`Failed to ${updateChart ? 'update' : 'create'} chart`)); 216 | console.log(JSON.parse(err.error)); 217 | }); 218 | 219 | /*=========================================*/ -------------------------------------------------------------------------------- /2020-10-18-trump-tweet-heatmap/data/tweet-stats.json: -------------------------------------------------------------------------------- 1 | { 2 | "tweets": 23829, 3 | "retweets": [ 4 | 2191, 5 | 9.194678752780225 6 | ], 7 | "original": [ 8 | 21638, 9 | 90.80532124721978 10 | ], 11 | "yearly": { 12 | "2017": [ 13 | 21228, 14 | 89.08472869193 15 | ], 16 | "2018": [ 17 | 20261, 18 | 85.02664820177095 19 | ], 20 | "2019": [ 21 | 16017, 22 | 67.21641697091779 23 | ], 24 | "2020": [ 25 | 13981, 26 | 58.67220613538126 27 | ] 28 | }, 29 | "contains": { 30 | "great": [ 31 | 3226, 32 | 14.9089564654774 33 | ], 34 | "usa-america": [ 35 | 1277, 36 | 5.901654496718735 37 | ], 38 | "china": [ 39 | 548, 40 | 2.5325815694611333 41 | ], 42 | "trump": [ 43 | 1699, 44 | 7.851927165172382 45 | ], 46 | "republicans?": [ 47 | 885, 48 | 4.0900268046954436 49 | ], 50 | "democrats?": [ 51 | 1898, 52 | 8.771605508827063 53 | ], 54 | "!": [ 55 | 11477, 56 | 53.0409464830391 57 | ] 58 | }, 59 | "exclamationMarks": 14019, 60 | "device": { 61 | "Twitter for iPhone": 23045, 62 | "Twitter for Android": 281, 63 | "Twitter Web Client": 56, 64 | "Media Studio": 155, 65 | "Twitter Ads": 33, 66 | "Twitter for iPad": 38, 67 | "Twitter Media Studio": 214, 68 | "Twitter Web App": 7 69 | }, 70 | "loudness": 10.16226806276113 71 | } -------------------------------------------------------------------------------- /2020-10-18-trump-tweet-heatmap/get-stats.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const { argv } = require('yargs'); 3 | const chalk = require('chalk'); 4 | 5 | const { createChart } = require('./utils/dw-api-utils'); 6 | const { getLetters } = require('./utils/utils'); 7 | 8 | let tweetData = JSON.parse(fs.readFileSync('./data/all-tweets.json')); 9 | 10 | console.log(chalk.grey('Getting tweet stats...')); 11 | 12 | const words = [['great'],['usa','america'],['china'],['trump'],['republicans?'],['democrats?']]; 13 | const years = [2017,2018,2019,2020]; 14 | 15 | const retweets = tweetData.filter(t => t.is_retweet).length; 16 | const original = tweetData.length - retweets; 17 | 18 | const device = tweetData.reduce((acc,t) => { 19 | if (!acc[t.source]) acc[t.source] = []; 20 | acc[t.source]++; 21 | return acc; 22 | },{}); 23 | 24 | const yearly = years.reduce((acc,year) => { 25 | const tot = tweetData.filter(t => t.year !== year).length; 26 | acc[year] = [tot,100*tot/tweetData.length]; 27 | return acc; 28 | },{}); 29 | 30 | const contains = words.reduce((acc,wordSet) => { 31 | const re = new RegExp(`\\b(${wordSet.join('|')})\\b`, 'gmi'); 32 | const tot = tweetData.filter(t => !t.is_retweet && t.text.match(re)).length; 33 | acc[wordSet.join('-')] = [tot,100*tot/original]; 34 | return acc; 35 | },{}); 36 | 37 | 38 | let exclamationMarks = 0; 39 | 40 | const containExclamation = tweetData.filter(t => { 41 | if (t.text.includes('!')) exclamationMarks += t.text.match(/!/gm).length; 42 | return !t.is_retweet && t.text.includes('!')} 43 | ).length; 44 | 45 | contains["!"] = [containExclamation,100*containExclamation/original]; 46 | 47 | const loudness = 100*getLetters(tweetData,'[A-Z]')/getLetters(tweetData,'[a-zA-Z]'); 48 | 49 | const stats = { 50 | 'tweets':tweetData.length, 51 | 'retweets':[retweets,100*retweets/tweetData.length], 52 | 'original': [original,100*original/tweetData.length], 53 | 'yearly': yearly, 54 | 'contains': contains, 55 | 'exclamationMarks':exclamationMarks, 56 | device, 57 | loudness 58 | } 59 | 60 | fs.writeFileSync('./data/tweet-stats.json', JSON.stringify(stats, null, '\t')); 61 | console.log(chalk.green('Calculated stats and saved to tweet-stats.json')); -------------------------------------------------------------------------------- /2020-10-18-trump-tweet-heatmap/get-tweets.js: -------------------------------------------------------------------------------- 1 | const rp = require('request-promise'); 2 | const fs = require('fs'); 3 | const chalk = require('chalk'); 4 | const yearTweets = []; 5 | 6 | console.log(chalk.grey('Downloading tweets...')); 7 | 8 | const haveOldData = fs.existsSync('./data/previous-year-tweets.json'); 9 | 10 | let allTweets = haveOldData ? JSON.parse(fs.readFileSync('./data/previous-year-tweets.json')) : []; 11 | 12 | const years = haveOldData ? [2020] : [2017,2018,2019,2020]; 13 | 14 | const options = (year) => { 15 | const root = year !== 2020 ? 16 | 'http://d5nxcu7vtzvay.cloudfront.net/data/realdonaldtrump' : 17 | 'http://www.trumptwitterarchive.com/data/realdonaldtrump' 18 | return { 19 | method:'GET', 20 | uri:`${root}/${year}.json`, 21 | json:true 22 | } 23 | } 24 | 25 | function getTweets(year) { 26 | return rp(options(year)).then(res => { 27 | yearTweets.push([...res]); 28 | console.log(chalk.yellow(`Got ${year === 2020 ? 'latest' : ''} tweets from ${year}`)); 29 | }).catch(err => { 30 | console.log(chalk.red(`Failed to get data for ${year}`)); 31 | }) 32 | } 33 | const getAllTweets = async function() { 34 | 35 | for (i = 0; i < years.length ; i++) { 36 | await getTweets(years[i]); 37 | } 38 | 39 | yearTweets.forEach(year => { 40 | year.forEach(tweet => { 41 | var date = new Date(tweet.created_at); 42 | tweet.year = date.getFullYear(); 43 | tweet.day = date.getDate(); 44 | tweet.month = date.getMonth() + 1; 45 | }); 46 | year = year.sort((a,b) => { 47 | return new Date(a.created_at).getTime() - new Date(b.created_at).getTime(); 48 | }); 49 | }); 50 | 51 | if (!haveOldData) { 52 | const latestTweets = yearTweets.pop(); 53 | yearTweets.forEach(year => { 54 | allTweets.push(...year); 55 | }); 56 | fs.writeFileSync('./data/previous-year-tweets.json', JSON.stringify(allTweets , null,'\t')); 57 | allTweets.push(...latestTweets); 58 | } else { 59 | allTweets.push(...yearTweets[0]); 60 | } 61 | 62 | fs.writeFileSync('./data/all-tweets.json', JSON.stringify(allTweets,null,'\t')); 63 | console.log(chalk.green(`Downloaded ${haveOldData ? 'latest' : 'all'} tweets and saved to all-tweets.json`)); 64 | } 65 | 66 | getAllTweets(); -------------------------------------------------------------------------------- /2020-10-18-trump-tweet-heatmap/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "trump-tweets", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "all": "node get-tweets.js && node count-tweets.js && node get-stats.js && node create-heatmap.js --id" 9 | }, 10 | "keywords": [], 11 | "author": "", 12 | "license": "ISC", 13 | "dependencies": { 14 | "chalk": "^4.1.0", 15 | "d3-array": "^2.8.0", 16 | "d3-color": "^2.0.0", 17 | "d3-interpolate": "^2.0.1", 18 | "d3-scale": "^3.2.3", 19 | "dotenv": "^8.2.0", 20 | "moment": "^2.29.1", 21 | "request": "^2.88.2", 22 | "request-promise": "^4.2.6", 23 | "yargs": "^16.0.3" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /2020-10-18-trump-tweet-heatmap/trump-tweet-heatmap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2020-10-18-trump-tweet-heatmap/trump-tweet-heatmap.png -------------------------------------------------------------------------------- /2020-10-18-trump-tweet-heatmap/utils/dw-api-utils.js: -------------------------------------------------------------------------------- 1 | require('dotenv').config(); 2 | const rp = require('request-promise'); 3 | const chalk = require('chalk'); 4 | 5 | const options = ({id, method, endpoint, body, type}) => { 6 | const api = 'https://api.datawrapper.de'; 7 | const token = process.env.API_TOKEN; 8 | 9 | const opts = { 10 | 'method': method, 11 | 'url': `${api}/v3/charts${id ? '/'+ id : ''}${endpoint ? '/' + endpoint : ''}`, 12 | 'headers': { 13 | 'Authorization': `Bearer ${token}`, 14 | 'Accept': '*/*' 15 | } 16 | }; 17 | 18 | if (type) opts.headers["Content-Type"] = type === 'csv' ? 'text/csv' : 'application/json'; 19 | if (body) opts.body = type === 'json' ? JSON.stringify(body) : body; 20 | 21 | return opts; 22 | }; 23 | 24 | function addMetadata({metadata,data,id}) { 25 | const opts = { 26 | method: id ? "PATCH" : "POST", 27 | body:metadata, 28 | type:'json' 29 | }; 30 | if (id) opts.id = id; 31 | 32 | return rp(options(opts)) 33 | .then(response => { 34 | const chartId = JSON.parse(response).id; 35 | console.log(chalk.yellow(`${id ? 'Updated metadata for' : 'Created'} chart ${chartId}`)); 36 | return {id:chartId, data,update: id ? true : false}; 37 | }) 38 | .catch(err => { 39 | return {failedAt: id ? 'create chart' : 'update chart metadata',error:JSON.parse(err.error)}; 40 | }); 41 | } 42 | 43 | function addData({data,id,failedAt,error,update}) { 44 | if (error) return {error,failedAt}; 45 | 46 | return rp(options({id:id,method:"PUT", body:data, type:'csv', endpoint:'data'})) 47 | .then(response => { 48 | console.log(chalk.yellow(`${update ? 'Updated data for' : 'Uploaded data to'} ${id}`)); 49 | return {id:id} 50 | }) 51 | .catch(err => { 52 | return {failedAt:'add data',error:JSON.parse(err.error)}; 53 | }) 54 | } 55 | 56 | function publishChart(id) { 57 | return rp(options({id,method:'POST',endpoint:'publish'})); 58 | } 59 | 60 | function createChart({metadata,data,id,update}) { 61 | if (update === 'metadata') { 62 | return addMetadata({metadata,id}) 63 | } else if (update === 'data') { 64 | return addData({data,id}); 65 | } else { 66 | return addMetadata({metadata,data,id}).then(addData); 67 | } 68 | } 69 | 70 | exports.createChart = createChart; 71 | exports.publishChart = publishChart; -------------------------------------------------------------------------------- /2020-10-18-trump-tweet-heatmap/utils/utils.js: -------------------------------------------------------------------------------- 1 | const ttBody = ` 7 |
{{ most_popular_date.split(' - ')[0] }}, {{month.split('/')[2]}}
8 | {% if (most_popular_text) { %} 9 |
Most liked tweet:
10 |
11 |
12 | 13 |
14 | Donald J. Trump 15 | @realDonaldTrump 16 |
17 |
18 |
{{ most_popular_text }}
19 | 28 |
29 |
30 | {% } %}`; 31 | 32 | exports.tooltip = { 33 | "body": ttBody, 34 | "title": '{{ total }} tweets', 35 | "fields": { 36 | "day": "day", 37 | "month": "month", 38 | "total": "total", 39 | "likeRate": "likeRate", 40 | "original": "original", 41 | "retweets": "retweets", 42 | "totalLikes": "totalLikes", 43 | "total_color": "total-color", 44 | "highestLikes": "highestLikes", 45 | "totalRetweets": "totalRetweets", 46 | "likeRate_color": "likeRate-color", 47 | "original_color": "original-color", 48 | "retweets_color": "retweets-color", 49 | "most_popular_id": "most-popular-id", 50 | "totalLikes_color": "totalLikes-color", 51 | "most_popular_date": "most-popular-date", 52 | "most_popular_text": "most-popular-text", 53 | "highestLikes_color": "highestLikes-color", 54 | "totalRetweets_color": "totalRetweets-color" 55 | } 56 | }; 57 | 58 | exports.hlRange = `32,01/01/2017,33,01/01/2017,33,01/01/2018,32,01/01/2018 @stroke:#2fa3ee @width:1 @dashed @color:transparent @opacity:1 59 | 60 | 32,01/01/2018,33,01/01/2018,33,01/01/2019,32,01/01/2019 @stroke:#2fa3ee @width:1 @dashed @color:transparent @opacity:1 61 | 62 | 32,01/01/2019,33,01/01/2019,33,01/01/2020,32,01/01/2020 @stroke:#2fa3ee @width:1 @dashed @color:transparent @opacity:1 63 | 64 | 32,01/01/2020,33,01/01/2020,33,11/01/2020,32,11/01/2020 @stroke:#2fa3ee @width:1 @dashed @color:transparent @opacity:1 65 | 66 | 1,01/01/2017,1,01/01/2021 @color:#96d2f9 @dotted 67 | 2,01/01/2017,2,01/01/2021 @color:#96d2f9 @dotted 68 | 3,01/01/2017,3,01/01/2021 @color:#96d2f9 @dotted 69 | 4,01/01/2017,4,01/01/2021 @color:#96d2f9 @dotted 70 | 5,01/01/2017,5,01/01/2021 @color:#96d2f9 @dotted 71 | 6,01/01/2017,6,01/01/2021 @color:#96d2f9 @dotted 72 | 7,01/01/2017,7,01/01/2021 @color:#96d2f9 @dotted 73 | 8,01/01/2017,8,01/01/2021 @color:#96d2f9 @dotted 74 | 9,01/01/2017,9,01/01/2021 @color:#96d2f9 @dotted 75 | 10,01/01/2017,10,01/01/2021 @color:#96d2f9 @dotted 76 | 11,01/01/2017,11,01/01/2021 @color:#96d2f9 @dotted 77 | 12,01/01/2017,12,01/01/2021 @color:#96d2f9 @dotted 78 | 13,01/01/2017,13,01/01/2021 @color:#96d2f9 @dotted 79 | 14,01/01/2017,14,01/01/2021 @color:#96d2f9 @dotted 80 | 15,01/01/2017,15,01/01/2021 @color:#96d2f9 @dotted 81 | 16,01/01/2017,16,01/01/2021 @color:#96d2f9 @dotted 82 | 17,01/01/2017,17,01/01/2021 @color:#96d2f9 @dotted 83 | 18,01/01/2017,18,01/01/2021 @color:#96d2f9 @dotted 84 | 19,01/01/2017,19,01/01/2021 @color:#96d2f9 @dotted 85 | 20,01/01/2017,20,01/01/2021 @color:#96d2f9 @dotted 86 | 21,01/01/2017,21,01/01/2021 @color:#96d2f9 @dotted 87 | 22,01/01/2017,22,01/01/2021 @color:#96d2f9 @dotted 88 | 23,01/01/2017,23,01/01/2021 @color:#96d2f9 @dotted 89 | 24,01/01/2017,24,01/01/2021 @color:#96d2f9 @dotted 90 | 25,01/01/2017,25,01/01/2021 @color:#96d2f9 @dotted 91 | 26,01/01/2017,26,01/01/2021 @color:#96d2f9 @dotted 92 | 27,01/01/2017,27,01/01/2021 @color:#96d2f9 @dotted 93 | 28,01/01/2017,28,01/01/2021 @color:#96d2f9 @dotted 94 | 29,01/01/2017,29,01/01/2021 @color:#96d2f9 @dotted 95 | 30,01/01/2017,30,01/01/2021 @color:#96d2f9 @dotted 96 | 31,01/01/2017,31,01/01/2021 @color:#96d2f9 @dotted` 97 | 98 | exports.annotations = [ 99 | { 100 | "x": "33", 101 | "y": 1498100000000, 102 | "bg": false, 103 | "dx": "-7", 104 | "dy": 0, 105 | "bold": true, 106 | "size": 14, 107 | "text": "2\n0\n1\n7", 108 | "align": "mr", 109 | "color": "#3daef4", 110 | "italic": false, 111 | "underline": false, 112 | "showMobile": true, 113 | "showDesktop": true 114 | }, 115 | { 116 | "x": "33", 117 | "y": 1529700000000, 118 | "bg": false, 119 | "dx": "-7", 120 | "dy": 0, 121 | "bold": true, 122 | "size": 14, 123 | "text": "2\n0\n1\n8", 124 | "align": "mr", 125 | "color": "#3daef4", 126 | "italic": false, 127 | "underline": false, 128 | "showMobile": true, 129 | "showDesktop": true 130 | }, 131 | { 132 | "x": "33", 133 | "y": 1561300000000, 134 | "bg": false, 135 | "dx": "-7", 136 | "dy": 0, 137 | "bold": true, 138 | "size": 14, 139 | "text": "2\n0\n1\n9", 140 | "align": "mr", 141 | "color": "#3daef4", 142 | "italic": false, 143 | "underline": false, 144 | "showMobile": true, 145 | "showDesktop": true 146 | }, 147 | { 148 | "x": "33", 149 | "y": 1589300000000, 150 | "bg": false, 151 | "dx": "-7", 152 | "dy": 0, 153 | "bold": true, 154 | "size": 14, 155 | "text": "2\n0\n2\n0", 156 | "align": "mr", 157 | "color": "#3daef4", 158 | "italic": false, 159 | "underline": false, 160 | "showMobile": true, 161 | "showDesktop": true 162 | } 163 | ]; 164 | 165 | exports.notes = (colors,width,height,max) => { 166 | const gradient = colors.map((col,i) => { 167 | return `${col} ${100*i/(colors.length-1)}%` 168 | }).join(', '); 169 | 170 | return ` 171 | 172 | 173 | 174 | 175 | 176 | 0${Math.round(max/2)}${Math.round(max)} 177 | 178 | 179 | *includes retweets`; 180 | } 181 | 182 | exports.getMax = (prop,dailyTweets) => { 183 | let max = 0; 184 | Object.keys(dailyTweets).forEach(yearMonth => { 185 | Object.keys(dailyTweets[yearMonth]).forEach(day => { 186 | max = Math.max(dailyTweets[yearMonth][day][prop],max); 187 | }) 188 | }) 189 | return max; 190 | } 191 | 192 | exports.getLetters = (tweets,exp) => { 193 | const re = new RegExp(`${exp}`, 'gm'); 194 | return tweets.reduce((acc,t) => { 195 | if (!t.is_retweet) { 196 | const letters = t.text.replace(/https:\/\/[^\s]+/gm,'').replace(/\\n/gm,'').match(re); 197 | if (letters) { acc += letters.length;} 198 | } 199 | return acc; 200 | },0); 201 | } -------------------------------------------------------------------------------- /2021-05-27-weather-forecast/.gitignore: -------------------------------------------------------------------------------- 1 | out 2 | -------------------------------------------------------------------------------- /2021-05-27-weather-forecast/README.md: -------------------------------------------------------------------------------- 1 | this code generates the weather forecast table for my weekly chart 2 | -------------------------------------------------------------------------------- /2021-05-27-weather-forecast/forecast.csv: -------------------------------------------------------------------------------- 1 | day,sun,rain,temp 2 | Tue.,![](https://vis4.net/i/sun1.png) 3h,![](https://vis4.net/i/rain2.png) 6mm,"13 / 8°C" 3 | Wed.,![](https://vis4.net/i/sun0.png) 0h,![](https://vis4.net/i/rain3.png) 10mm,"12 / 8°C" 4 | Thu.,![](https://vis4.net/i/sun1.png) 2h,![](https://vis4.net/i/rain3.png) 8mm,"13 / 9°C" 5 | Fri.,![](https://vis4.net/i/sun2.png) 6h,![](https://vis4.net/i/rain0.png) 0mm,"15 / 8°C" 6 | Sat.,![](https://vis4.net/i/sun2.png) 9h,![](https://vis4.net/i/rain0.png) 0mm,"18 / 8°C" 7 | Sun.,![](https://vis4.net/i/sun3.png) 11h,![](https://vis4.net/i/rain0.png) 0mm,"20 / 9°C" 8 | Mon.,![](https://vis4.net/i/sun3.png) 11h,![](https://vis4.net/i/rain0.png) 0mm,"21 / 11°C" 9 | Tue.,![](https://vis4.net/i/sun2.png) 9h,![](https://vis4.net/i/rain0.png) 0mm,"22 / 12°C" 10 | Wed.,![](https://vis4.net/i/sun2.png) 9h,![](https://vis4.net/i/rain0.png) 0mm,"22 / 13°C" 11 | Thu.,![](https://vis4.net/i/sun2.png) 8h,![](https://vis4.net/i/rain0.png) 0mm,"22 / 13°C" 12 | -------------------------------------------------------------------------------- /2021-05-27-weather-forecast/weather-forecast-table.R: -------------------------------------------------------------------------------- 1 | # install.packages('devtools') 2 | # library('devtools') 3 | # devtools::install_github("retostauffer/Rmosmix") 4 | # library("mosmix") 5 | library(readr) 6 | library(dplyr) 7 | library(weathermetrics) 8 | library(mosmix) 9 | library(rjson) 10 | 11 | station_id <- 'C720' # Berlin-Tempelhof 12 | 13 | # url <- paste0('https://opendata.dwd.de/weather/local_forecasts/mos/MOSMIX_L/single_stations/', station_id, '/kml/MOSMIX_L_LATEST_',station_id,'.kmz') 14 | url <- 'https://opendata.dwd.de/weather/local_forecasts/mos/MOSMIX_S/all_stations/kml/MOSMIX_S_LATEST_240.kmz' 15 | 16 | kmz <- tempfile("mosmix_demo_", fileext = ".kmz") 17 | check <- download.file(url, kmz) 18 | 19 | if ( inherits(check, "try-error") ) stop("Problems downloading the file!") 20 | kml <- unzip(kmz) 21 | 22 | doc <- XML::xmlParse(kml) 23 | datetime <- get_datetime(doc) 24 | meta <- get_meta_info(doc) 25 | 26 | 27 | if (file.exists('out/stations.csv')) { 28 | good.stations <- read_csv('out/stations.csv') 29 | } else { 30 | stations <- read_fwf('https://www.dwd.de/EN/ourservices/met_application_mosmix/mosmix_stations.cfg;jsessionid=6A47F126BB1F3B5383F07B7CC03595E9.live31092?view=nasPublication&nn=495490', 31 | col_positions = fwf_widths(c(5,6,6,5,21,7,8,6,7,5), 32 | col_names = c('clu','CofX','id','ICAO', 'name','lat','lon','elev','Hmod-H', 'type')), skip = 4) 33 | good.stations <- stations 34 | } 35 | 36 | now <- Sys.time() 37 | final_stations <- c() 38 | 39 | dir.create('out', showWarnings=F) 40 | dir.create('out/stations', showWarnings = F) 41 | 42 | for (station_id in good.stations$id) { 43 | fcst <- get_forecasts(station_id, doc, datetime, meta, as.zoo = FALSE) 44 | if (!is.null(fcst) & !is.null(fcst$SunD1)) { 45 | by.day <- fcst %>% 46 | transmute(date=as.Date(datetime), 47 | temp=kelvin.to.celsius(TTT), 48 | sun=SunD1/60, 49 | rain=RR1c) %>% 50 | group_by(date) %>% 51 | filter(n()==24) %>% 52 | summarise(temp.min=round(min(temp)), temp.max=round(max(temp)), sunshine.hours=round(sum(sun)/60,0), rain.mm=sum(rain)) 53 | 54 | by.day %>% 55 | transmute(day=format(date, '%a.'), 56 | sun=paste0('![](https://vis4.net/i/sun', as.numeric(cut(sunshine.hours, breaks=c(-1,0.5,4,9,24)))-1,'.png) ', sunshine.hours, 'h'), 57 | rain=paste0('![](https://vis4.net/i/rain',as.numeric(cut(rain.mm, breaks=c(-1,0,2,6,100)))-1,'.png) ', round(rain.mm), 'mm'), 58 | temp=paste0(temp.max,' / ', temp.min,'°C')) %>% 59 | write_csv(paste0('out/stations/forecast-', station_id, '.csv')) 60 | 61 | final_stations <- append(final_stations, station_id) 62 | print(station_id) 63 | } 64 | } 65 | 66 | if (!file.exists('out/stations.csv')) { 67 | good.stations %>% filter(id %in% final_stations) %>% write_csv('out/stations.csv') 68 | } 69 | 70 | json <- toJSON(list(describe=list(intro=paste0('', format(now, '%B %d, %Y'),'')), 71 | annotate=list(notes=format(now, 'Last updated at %I:%M%p on %B %d, %Y')))) 72 | write(json, 'out/last-update.json') 73 | 74 | f <- file('out/last-update.txt') 75 | writeLines(as.character(now), f) 76 | close(f) 77 | 78 | unlink(kml) 79 | 80 | -------------------------------------------------------------------------------- /2021-06-17-game-of-life/README.md: -------------------------------------------------------------------------------- 1 | # Game of Life 2 | 3 | Includes the following Node.js scripts used in the Game of Life weekly chart: 4 | 5 | - `csv_script.js`: takes an initial state and number of steps as inputs and outputs CSV data files for each step 6 | - `api_script.js`: uses CSV data files to upload data and export a PNG image for each step. You will need to enter your own (existing) chart ID and an API token for this to work 7 | 8 | Game of Life animation 9 | 10 | 👉 [Link to Weekly chart article](https://blog.datawrapper.de/game-of-life/) 11 | 12 | ### Notes 13 | 14 | You need to have [Node.js](https://nodejs.org/en/) installed on your system in order to run these scripts. Install dependencies first by running `npm i`. Execute the script by running `node script.js`. 15 | -------------------------------------------------------------------------------- /2021-06-17-game-of-life/api_script.js: -------------------------------------------------------------------------------- 1 | const { createWriteStream } = require('fs'); 2 | const { pipeline } = require('stream'); 3 | const { promisify } = require('util'); 4 | const fetch = require('node-fetch'); 5 | const glob = require('glob'); 6 | const fs = require('fs'); 7 | 8 | const streamPipeline = promisify(pipeline); 9 | 10 | // Datawrapper chart id 11 | const id = 'XXXXX'; 12 | // Datawrapper API token. Needs to have chart read and write permissions 13 | const token = 'Bearer XXXX'; 14 | 15 | const dataUrl = `https://api.datawrapper.de/v3/charts/${id}/data`; 16 | const dataOptions = { 17 | method: 'PUT', 18 | headers: { 19 | Accept: '*/*', 20 | 'Content-Type': 'text/csv', 21 | Authorization: token 22 | } 23 | }; 24 | 25 | const exportUrl = `https://api.datawrapper.de/v3/charts/${id}/export/png?plain=true`; 26 | const exportOptions = { 27 | method: 'GET', 28 | headers: { 29 | Accept: 'image/png', 30 | Authorization: token 31 | } 32 | }; 33 | 34 | async function uploadDataAndExportPng(csvFiles) { 35 | if (!csvFiles.length) return console.log('finished'); 36 | const csvFile = csvFiles[0]; 37 | const csv = fs.readFileSync(csvFile, 'utf-8'); 38 | const stepName = csvFile.substr(csvFile.lastIndexOf('/') + 1).replace('.csv', ''); 39 | 40 | const dataOptionsWithBody = { ...dataOptions }; 41 | dataOptionsWithBody.body = csv; 42 | const uploadRes = await fetch(dataUrl, dataOptionsWithBody); 43 | if (!uploadRes.ok) throw new Error(`unexpected upload response ${uploadRes.statusText}`); 44 | 45 | const exportRes = await fetch(exportUrl, exportOptions); 46 | if (!exportRes.ok) throw new Error(`unexpected export response ${exportRes.statusText}`); 47 | await streamPipeline(exportRes.body, createWriteStream(`./${stepName}.png`)); 48 | console.log(`${stepName}.png written`); 49 | 50 | csvFiles.shift(); 51 | uploadDataAndExportPng(csvFiles); 52 | } 53 | 54 | const csvFiles = glob.sync('./*.csv'); 55 | uploadDataAndExportPng(csvFiles); 56 | -------------------------------------------------------------------------------- /2021-06-17-game-of-life/csv_script.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | 3 | const size = [36, 23]; // determines number of columns and rows in csv 4 | const width = size[0]; 5 | const height = size[1]; 6 | const headers = [...Array(width).keys()]; 7 | const numSteps = 80; 8 | let liveCells = []; 9 | 10 | // following string is taken from https://www.conwaylife.com/patterns/gosperglidergun.cells 11 | // more patterns can be found here: https://conwaylife.com/wiki/Category:Patterns 12 | const data = `........................O 13 | ......................O.O 14 | ............OO......OO............OO 15 | ...........O...O....OO............OO 16 | OO........O.....O...OO 17 | OO........O...O.OO....O.O 18 | ..........O.....O.......O 19 | ...........O...O 20 | ............OO`; 21 | 22 | function isLiveCell(pos) { 23 | return !!liveCells.find(cell => cell[0] === pos[0] && cell[1] === pos[1]); 24 | } 25 | 26 | function initLiveCells() { 27 | const dataRows = data.split('\n'); 28 | for (let row = 0; row < dataRows.length; row++) { 29 | for (let col = 0; col < dataRows[row].length; col++) { 30 | const value = dataRows[row]?.[col]; 31 | if (value === 'O') liveCells.push([col, row]); 32 | } 33 | } 34 | } 35 | 36 | function getNeighbors(pos) { 37 | const neighbors = []; 38 | for (let row = -1; row <= 1; row++) { 39 | for (let col = -1; col <= 1; col++) { 40 | if (!(row === 0 && col === 0)) neighbors.push([pos[0] + col, pos[1] + row]); 41 | } 42 | } 43 | return neighbors; 44 | } 45 | 46 | function updateLiveCells() { 47 | const positionsToCheckWithDupes = []; 48 | liveCells.forEach(liveCell => { 49 | const neighbors = getNeighbors(liveCell); 50 | positionsToCheckWithDupes.push(liveCell, ...neighbors); 51 | }); 52 | const map = new Map(); 53 | positionsToCheckWithDupes.forEach(item => map.set(item.join(), item)); 54 | const positionsToCheck = Array.from(map.values()); 55 | const newLiveCells = []; 56 | positionsToCheck.forEach(pos => { 57 | const neighbors = getNeighbors(pos); 58 | const numLiveNeighbors = neighbors.filter(neighborPos => isLiveCell(neighborPos)).length; 59 | if (numLiveNeighbors === 3 || (isLiveCell(pos) && numLiveNeighbors === 2)) { 60 | newLiveCells.push(pos); 61 | } 62 | }); 63 | liveCells = newLiveCells; 64 | } 65 | 66 | function padWithZeros(step) { 67 | const stepDigits = step.toString().length; 68 | const totalStepsDigits = numSteps.toString().length; 69 | return '0'.repeat(totalStepsDigits - stepDigits); 70 | } 71 | 72 | function toCsv(step) { 73 | let text = headers.join(','); 74 | text += '\n'; 75 | for (let row = 0; row < height; row++) { 76 | for (let col = 0; col < width; col++) { 77 | text += isLiveCell([col, row]) ? '1' : '0'; 78 | if (col < width - 1) text += ','; 79 | } 80 | text += '\n'; 81 | } 82 | const fname = `step-${padWithZeros(step)}${step}.csv`; 83 | fs.writeFile(`./${fname}`, text, err => { 84 | if (err) return console.log(err); 85 | console.log(`${fname} written`); 86 | }); 87 | } 88 | 89 | for (let step = 0; step <= numSteps; step++) { 90 | if (step === 0) initLiveCells(); 91 | else updateLiveCells(); 92 | toCsv(step); 93 | } 94 | -------------------------------------------------------------------------------- /2021-06-17-game-of-life/game-of-life.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2021-06-17-game-of-life/game-of-life.gif -------------------------------------------------------------------------------- /2021-06-17-game-of-life/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "game-of-life", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "Ivan Lokhov", 11 | "license": "ISC", 12 | "dependencies": { 13 | "glob": "^7.1.7", 14 | "node-fetch": "^2.6.1" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /2021-08-05-summer-winter-olympics-temperature/ellipse-jitter.R: -------------------------------------------------------------------------------- 1 | ellipse.jitter <- function(x,y,radius,scale.major,scale.minor) { 2 | x.jitter <- radius*scale.major 3 | y.jitter <- radius*scale.minor 4 | while((x.jitter*scale.minor*radius)^2 + 5 | (y.jitter*scale.major*radius)^2 - 6 | (scale.major*radius*scale.minor*radius)^2 > 0) { 7 | x.jitter <- runif(1,-radius*scale.major,radius*scale.major) 8 | y.jitter <- runif(1,-radius*scale.minor,radius*scale.minor) 9 | } 10 | return(data.frame('x.jittered' = x + x.jitter, 'y.jittered' =y + y.jitter)) 11 | } 12 | 13 | 14 | jitter.dataframe <- function(dataframe,x.column,y.column,radius.column,scale.major,scale.minor){ 15 | jitters <- data.frame('x.jittered' = numeric(0), 'y.jittered' = numeric(0)) 16 | for (i in 1:nrow(dataframe)) { 17 | point <- slice(dataframe,i) 18 | coordinates.jittered <- ellipse.jitter(pull(point,x.column), pull(point,y.column), pull(point,radius.column), scale.major, scale.minor) 19 | jitters <- bind_rows(jitters,coordinates.jittered) 20 | } 21 | dataframe <- bind_cols(dataframe,jitters) 22 | return(dataframe) 23 | } 24 | -------------------------------------------------------------------------------- /2021-08-05-summer-winter-olympics-temperature/readme.md: -------------------------------------------------------------------------------- 1 | This is a tiny R function to jitter points within an ellipse of specified size. 2 | 3 | You can use it to create Datawrapper charts like the one in [this Weekly Chart article](https://blog.datawrapper.de/summer-winter-olympics-temperature/) about summer and winter Olympic athletes. 4 | -------------------------------------------------------------------------------- /2022-01-06-function-names/form.csv: -------------------------------------------------------------------------------- 1 | "Timestamp","check()","compute()","fetch()","find()","filter()","get()","lookup()","parse()","pick()","search()","select()","read()" 2 | "2021/12/17 4:07:23 PM GMT+1","5","10","1","8","3","2","7","5","2","7","2","5" 3 | "2021/12/17 4:21:02 PM GMT+1","8","1","6","8","5","10","7","6","9","4","10","8" 4 | "2021/12/17 4:28:28 PM GMT+1","10","8","3","6","8","8","3","5","9","2","1","3" 5 | "2021/12/17 4:29:49 PM GMT+1","10","9","5","9","10","10","10","6","8","5","4","3" 6 | "2021/12/17 4:38:33 PM GMT+1","9","4","1","5","8","10","4","3","7","2","6","4" 7 | "2021/12/17 6:58:27 PM GMT+1","1","6","2","10","7","2","3","3","5","9","5","4" 8 | "2021/12/20 11:59:00 AM GMT+1","1","4","10","7","8","2","6","5","2","9","3","7" 9 | "2021/12/21 1:09:32 PM GMT+1","9","4","5","3","6","8","6","7","8","7","8","7" 10 | "2022/01/03 7:27:27 PM GMT+1","9","1","2","7","6","10","4","3","8","4","7","5" 11 | -------------------------------------------------------------------------------- /2022-01-06-function-names/google_form.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-01-06-function-names/google_form.png -------------------------------------------------------------------------------- /2022-01-06-function-names/result.csv: -------------------------------------------------------------------------------- 1 | function,1,2,3,4,5,6,7,8,9,10,mean 2 | find(),0.0,0.0,1.0,0.0,1.0,1.0,2.0,2.0,1.0,1.0,7.0 3 | check(),2.0,0.0,0.0,0.0,1.0,0.0,0.0,1.0,3.0,2.0,6.888888888888889 4 | get(),0.0,3.0,0.0,0.0,0.0,0.0,0.0,2.0,0.0,4.0,6.888888888888889 5 | filter(),0.0,0.0,1.0,0.0,1.0,2.0,1.0,3.0,0.0,1.0,6.777777777777778 6 | pick(),0.0,2.0,0.0,0.0,1.0,0.0,1.0,3.0,2.0,0.0,6.444444444444445 7 | lookup(),0.0,0.0,2.0,2.0,0.0,2.0,2.0,0.0,0.0,1.0,5.555555555555555 8 | search(),0.0,2.0,0.0,2.0,1.0,0.0,2.0,0.0,2.0,0.0,5.444444444444445 9 | compute(),2.0,0.0,0.0,3.0,0.0,1.0,0.0,1.0,1.0,1.0,5.222222222222222 10 | select(),1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,0.0,1.0,5.111111111111111 11 | read(),0.0,0.0,2.0,2.0,2.0,0.0,2.0,1.0,0.0,0.0,5.111111111111111 12 | parse(),0.0,0.0,3.0,0.0,3.0,2.0,1.0,0.0,0.0,0.0,4.777777777777778 13 | fetch(),2.0,2.0,1.0,0.0,2.0,1.0,0.0,0.0,0.0,1.0,3.888888888888889 14 | -------------------------------------------------------------------------------- /2022-06-30-background-colors/808s-heartbreak.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/808s-heartbreak.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/Screenshot 2022-06-30 at 10.28.31.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/Screenshot 2022-06-30 at 10.28.31.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/a-life-on-the-plannet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/a-life-on-the-plannet.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/a-snapshot-of-tate-museums.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/a-snapshot-of-tate-museums.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/a-story-about-hearing-yourself-represented-with-same-gender-lyrics-for-the-first-time.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/a-story-about-hearing-yourself-represented-with-same-gender-lyrics-for-the-first-time.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/an-open-question-survey.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/an-open-question-survey.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/apple-music-rapped.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/apple-music-rapped.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/art.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/art.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/arts-blooming-in-ohio.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/arts-blooming-in-ohio.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/best-animated-movies.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/best-animated-movies.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/campaign-colors.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/campaign-colors.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/can-data-die.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/can-data-die.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/climate-change-by-generation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/climate-change-by-generation.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/clubbing-feels.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/clubbing-feels.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/college-spirit-songs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/college-spirit-songs.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/colors-of-van-gogh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/colors-of-van-gogh.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/colour-symbolism-in-the-great-gatsby.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/colour-symbolism-in-the-great-gatsby.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/comedy-in-huntsville.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/comedy-in-huntsville.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/compositions-of-ludwig-van-beethoven.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/compositions-of-ludwig-van-beethoven.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/counting-the-cost-of-the-education-revolution.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/counting-the-cost-of-the-education-revolution.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/creating-demand-for-digital-art.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/creating-demand-for-digital-art.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/crypto-art.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/crypto-art.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/de-tijd-background-color.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/de-tijd-background-color.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/detailed-analysis-of-movies.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/detailed-analysis-of-movies.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/do-women-speak-to-each-other.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/do-women-speak-to-each-other.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/egot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/egot.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/financial-times-background-color.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/financial-times-background-color.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/following-the-science.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/following-the-science.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/frontliner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/frontliner.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/gallup-background-color.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/gallup-background-color.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/getting-creative-with-the-economy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/getting-creative-with-the-economy.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/good-teachers-are-kind.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/good-teachers-are-kind.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/guest-on-the-ellen-degeneres-show.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/guest-on-the-ellen-degeneres-show.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/hamilton.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/hamilton.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/health-care-journey.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/health-care-journey.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/how-encanto-songs-make-me-feel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/how-encanto-songs-make-me-feel.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/how-kerala’s-dams-failed-to-prevent-catastrophe.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/how-kerala’s-dams-failed-to-prevent-catastrophe.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/how-music-is-remembered.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/how-music-is-remembered.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/how-officer-complaints-are-investigated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/how-officer-complaints-are-investigated.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/how-to-make-a-hit-movie.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/how-to-make-a-hit-movie.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/how-you-play-spades-is-how-you-play-life.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/how-you-play-spades-is-how-you-play-life.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/james-bond-movie-franchise.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/james-bond-movie-franchise.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/james-bond-theme-song.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/james-bond-theme-song.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/last-words.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/last-words.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/lebron-james-fan-favorite.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/lebron-james-fan-favorite.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/lightning-cost.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/lightning-cost.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/live-music-analyst.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/live-music-analyst.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/masculinity.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/masculinity.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/measuring-radio's-lag-behind-streaming-services.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/measuring-radio's-lag-behind-streaming-services.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/mike-and-tom-eat-snacks.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/mike-and-tom-eat-snacks.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/netflix-oscars-viz.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/netflix-oscars-viz.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/new-america-background-color.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/new-america-background-color.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/next-to-normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/next-to-normal.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/nft---digital-art.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/nft---digital-art.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/ode-to-cinema.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/ode-to-cinema.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/oreos-and-the-art-of-crossword-puzzle-construction.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/oreos-and-the-art-of-crossword-puzzle-construction.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/palette-of-art.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/palette-of-art.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/pixar-in-theaters.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/pixar-in-theaters.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/putin-world-address.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/putin-world-address.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/rambling-through-the-avenues-of-time.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/rambling-through-the-avenues-of-time.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/rats.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/rats.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/reading-habits.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/reading-habits.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/remote-work-survey.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/remote-work-survey.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/rothko-artworks-at-the-national-gallery-of-art.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/rothko-artworks-at-the-national-gallery-of-art.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/saroj-khan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/saroj-khan.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/sherlock-holmes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/sherlock-holmes.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/sourav-karwa-spotify-weekly-top-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/sourav-karwa-spotify-weekly-top-200.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/space-junk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/space-junk.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/spotify-top-50-songs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/spotify-top-50-songs.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/spotify.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/spotify.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/stand-out-of-the-shadows.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/stand-out-of-the-shadows.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/streaming-service-comparisons.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/streaming-service-comparisons.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/sweet-slim-greasy-grim.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/sweet-slim-greasy-grim.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/taylor-swift.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/taylor-swift.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/the-art-of-conversation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/the-art-of-conversation.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/the-art-of.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/the-art-of.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/the-arts-in-singapore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/the-arts-in-singapore.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/the-beat-lives-on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/the-beat-lives-on.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/the-buran.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/the-buran.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/the-discography-of-deadmau5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/the-discography-of-deadmau5.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/the-economist-new.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/the-economist-new.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/the-economist-old.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/the-economist-old.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/the-faces-of-a-nation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/the-faces-of-a-nation.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/the-firebird-suite.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/the-firebird-suite.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/the-funniest-ted-talks.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/the-funniest-ted-talks.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/the-genres-of-acl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/the-genres-of-acl.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/the-rise-of-nft-art.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/the-rise-of-nft-art.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/the-singlit-movement.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/the-singlit-movement.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/the-times-background-color.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/the-times-background-color.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/the-vast-legacy-and-miserable-life-of-vincent-van-gogh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/the-vast-legacy-and-miserable-life-of-vincent-van-gogh.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/thearttheartist.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/thearttheartist.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/this-is-an-experiment-about-how-we-view-history.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/this-is-an-experiment-about-how-we-view-history.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/top-popular-movies.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/top-popular-movies.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/vincent-van-gogh-letters.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/vincent-van-gogh-letters.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/visualisation-of-arts.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/visualisation-of-arts.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/was-yesterday-a-heat-record.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/was-yesterday-a-heat-record.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/we-couldn’t-get-an-artificial-intelligence-program-to-win-the-new-yorker-caption-contest.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/we-couldn’t-get-an-artificial-intelligence-program-to-win-the-new-yorker-caption-contest.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/we-found-this-cool-study-about-randomness.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/we-found-this-cool-study-about-randomness.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/when-women-make-headlines.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/when-women-make-headlines.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/whos-in-your-wallet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/whos-in-your-wallet.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/why-are-k-pop-groups-so-big.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/why-are-k-pop-groups-so-big.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/wine-and-math.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/wine-and-math.png -------------------------------------------------------------------------------- /2022-06-30-background-colors/women-in-film.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2022-06-30-background-colors/women-in-film.png -------------------------------------------------------------------------------- /2023-11-R-demo/R-script: -------------------------------------------------------------------------------- 1 | # install packages 2 | install.packages('devtools') 3 | devtools::install_github('munichrocker/DatawRappr') 4 | install.packages('rdwd') 5 | 6 | library(DatawRappr) 7 | library(rdwd) 8 | 9 | datawrapper_auth(api_key = Sys.getenv('WEBINAR_TOKEN'), overwrite = TRUE ) 10 | 11 | dw_test_key() 12 | 13 | folder <- dw_create_folder('APIcharts') 14 | folder_id <- folder[['id']] 15 | 16 | # ----- create function! 17 | create_line_chart <- function(city) { 18 | 19 | # load, clean and prepare data 20 | cities_data <- selectDWD(city, res='daily', var='kl', per='recent') 21 | file <- dataDWD(cities_data, read=FALSE) 22 | clim <- readDWD(file, varnames=TRUE) 23 | subset_clim <- clim[, c('MESS_DATUM', 'TXK.Lufttemperatur_Max', 'TNK.Lufttemperatur_Min')] 24 | names(subset_clim)[names(subset_clim) == 'TXK.Lufttemperatur_Max'] <- 'Max' 25 | names(subset_clim)[names(subset_clim) == 'TNK.Lufttemperatur_Min'] <- 'Min' 26 | 27 | # create datawrapper line chart 28 | line <- dw_create_chart( 29 | folderId = folder_id, 30 | type = 'd3-lines' 31 | ) 32 | 33 | line_id <- line[['content']][['publicId']] 34 | 35 | dw_data_to_chart( 36 | subset_clim, 37 | chart_id = line_id 38 | ) 39 | 40 | dw_edit_chart( 41 | chart_id = line_id, 42 | folderId = folder_id, 43 | 44 | title = sprintf('Daily temperatures in %s ', city), 45 | intro = 'Daily temperature in Celsius degrees', 46 | byline = 'Guillermina Sutter Schneider', 47 | 48 | annotate = sprintf('This chart was updated on %s', format(Sys.time(), "%a %b %d %X %Y")), 49 | 50 | describe = list( 51 | 'source-name' = 'German Weather Service (DWD)', 52 | 'source-url' = 'https://opendata.dwd.de/climate_environment/CDC/observations_germany/climate/' 53 | ), 54 | 55 | visualize = list( 56 | 'custom-colors' = list( 57 | 'Max' = '#09bb9f', 58 | 'Min' = '#1d81a2' 59 | ), 60 | 61 | 'line-widths' = list( 62 | 'Max' = 3, 63 | 'Min' = 3), 64 | 65 | 'labeling' = 'top', 66 | 67 | 'line-symbols' = TRUE, 68 | 'line-symbols-on' = 'both', 69 | 'line-symbols-size' = 3.5, 70 | 'line-symbols-shape' = 'circle', 71 | 72 | 'custom-area-fills' = list( 73 | list( 74 | 'to' = 'Min', 75 | 'from' = 'Max', 76 | 'color' = '#cccccc', 77 | 'opacity' = 0.3 78 | ) 79 | ) 80 | 81 | ) 82 | 83 | ) 84 | 85 | dw_publish_chart( 86 | chart_id = line_id, 87 | return_urls = TRUE 88 | ) 89 | 90 | } 91 | 92 | create_line_chart('Bamberg') 93 | 94 | city_list <- list('Frankfurt/Main', 'Garmisch-Partenkirchen', 'Berlin Brandenburg', 95 | 'Erfurt-Weimar', 'Koeln-Bonn', 'Potsdam', 'Muenchen-Stadt', 96 | 'Arkona', 'Wuerzburg') 97 | -------------------------------------------------------------------------------- /2023-11-R-demo/README.md: -------------------------------------------------------------------------------- 1 | # R script from the _Datawrapper API: A beginner's guide with R_ webinar 2 | You'll find the R script to replicate the demo example [here](https://github.com/datawrapper/snippets/blob/master/2023-11-R-demo/R-script). 3 | 4 | The script shows how to install the necessary packages and build a function `create_line_chart` that does the following: 5 | 1. load, clean and prepare data from the [German Weather Service](https://bookdown.org/brry/rdwd/#usage) 6 | 2. create a line chart 7 | 3. add data to the chart 8 | 4. edit the chart 9 | 5. publish the chart 10 | 11 | Use that function to create multiple charts at once through a list of cities. 12 | 13 | An example of the chart that's created by this function is shown below. 14 | 15 | ![Line chart of max and min temperatures in Potsdam](https://github.com/datawrapper/snippets/blob/master/2023-11-R-demo/daily-temperatures-potsdam.png) 16 | 17 | You can read more about our API documentation [here](https://developer.datawrapper.de/docs/getting-started). 18 | -------------------------------------------------------------------------------- /2023-11-R-demo/daily-temperatures-potsdam.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datawrapper/snippets/5f135bfa6fed58c98d145094bd48116f4ecad8c5/2023-11-R-demo/daily-temperatures-potsdam.png -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Datawrapper 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # snippets 2 | Small but useful code snippets from folks who work at Datawrapper 3 | --------------------------------------------------------------------------------