├── fonts
├── fa-solid-900.ttf
├── fa-brands-400.ttf
└── fa-regular-400.ttf
├── R
├── 2024
│ ├── week_09
│ │ ├── dificultades.csv
│ │ └── README.md
│ ├── week_07
│ │ └── README.md
│ ├── week_08
│ │ └── README.md
│ ├── week_01
│ │ ├── README.md
│ │ └── eolica.csv
│ ├── week_03
│ │ ├── README.md
│ │ └── 2024_w03_calendar.R
│ ├── week_05
│ │ ├── README.md
│ │ └── salarios.csv
│ ├── week_02
│ │ ├── README.md
│ │ ├── eco_farms_poland.csv
│ │ └── 2024_w02_lego_map.R
│ ├── week_04
│ │ └── README.md
│ ├── week_10
│ │ ├── README.md
│ │ └── gender_pay_gap_2022.csv
│ ├── week_11
│ │ └── README.md
│ ├── week_06
│ │ ├── README.md
│ │ └── median_net_wealth_by_age.csv
│ ├── week_12
│ │ ├── README.md
│ │ ├── portfolio.csv
│ │ └── 2024_w12_portfolio.R
│ ├── week_47
│ │ └── forecast_11_2024.csv
│ └── week_49
│ │ └── 2024_w47.R
├── 30DayChartChallenge2024
│ ├── day_18
│ │ ├── KIDB.xlsx
│ │ ├── exchange.csv
│ │ └── day_18_asian_development_bank.R
│ ├── theme
│ │ ├── fa-brands-400.ttf
│ │ ├── fa-solid-900.ttf
│ │ └── styles.R
│ ├── day_14
│ │ ├── no2_calendar_data.csv
│ │ └── day_14_heatmap.R
│ ├── day_08
│ │ ├── pm10_mean_zona_2001.RDS
│ │ └── day_8_circular.R
│ ├── day_03
│ │ ├── Public_Awareness_Around_Antibiotic_Resistance.png
│ │ └── day_3_makeover.R
│ ├── day_22
│ │ └── rail_passengers.csv
│ ├── day_02
│ │ ├── death-rates-from-energy-production-per-twh.csv
│ │ └── day_02_neo.R
│ ├── day_13
│ │ ├── storks.csv
│ │ └── day_13_family.R
│ ├── day_10
│ │ ├── physical.csv
│ │ └── day_10_physical.R
│ ├── day_27
│ │ ├── forecast.csv
│ │ └── day_27_GoodBad.R
│ ├── day_21
│ │ ├── energy.csv
│ │ └── day_21_green_energy.R
│ ├── day_26
│ │ ├── ai.csv
│ │ └── day_26_AI.R
│ ├── day_07
│ │ ├── hectares_burned_spain.csv
│ │ └── day_7_hazards.R
│ ├── day_29
│ │ └── day_29_black_n_white.R
│ ├── day_17
│ │ └── day_17_networks.R
│ ├── day_01
│ │ └── day_01_part_to_whole.R
│ ├── day_24
│ │ └── day_24_ILO_Africa.R
│ ├── day_09
│ │ └── day_9_major_minor.R
│ ├── day_19
│ │ ├── multiTimeline.csv
│ │ └── day_19_dinosaurs.R
│ ├── day_05
│ │ └── day_5_diverging.R
│ ├── cfg
│ │ └── plots.yml
│ ├── day_15
│ │ └── day_15_historical.R
│ ├── day_20
│ │ └── day_20_correlation.R
│ └── day_28
│ │ └── trend_tourist.csv
└── 30DayChartChallenge2025
│ ├── data
│ ├── day_1.csv
│ ├── day_4.csv
│ ├── ipca_mensual.csv
│ ├── epa_paro_ccaa.csv
│ ├── ipv_trimestral.csv
│ ├── salario_modal.csv
│ └── Distritos
│ │ ├── DISTRITOS.sbn
│ │ └── DISTRITOS.sbx
│ ├── category_4_timeseries
│ ├── day_22_stars
│ │ └── day_22.R
│ ├── day_19_smooth
│ │ └── day_19.R
│ ├── day_23_logscale
│ │ └── day_23.R
│ └── day_24_who
│ │ └── day_24.R
│ ├── category_1_comparisons
│ ├── day_1_fractions
│ │ └── day_1.R
│ └── day_5_ranking
│ │ └── day_5.R
│ ├── category_3_relationships
│ ├── day_15_complicated
│ │ └── day_15.R
│ └── day_18_el_pais
│ │ └── day_18.R
│ ├── utils.R
│ ├── category_2_distributions
│ └── day_11_stripes
│ │ └── day_11.R
│ ├── 30DayChartChallenge2025.yml
│ └── category_5_uncertainties
│ └── day_28_inclusion
│ └── day_28.R
├── dataviz.Rproj
├── LICENSE
├── .gitignore
└── README.md
/fonts/fa-solid-900.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/michal0091/dataviz/HEAD/fonts/fa-solid-900.ttf
--------------------------------------------------------------------------------
/fonts/fa-brands-400.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/michal0091/dataviz/HEAD/fonts/fa-brands-400.ttf
--------------------------------------------------------------------------------
/fonts/fa-regular-400.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/michal0091/dataviz/HEAD/fonts/fa-regular-400.ttf
--------------------------------------------------------------------------------
/R/2024/week_09/dificultades.csv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/michal0091/dataviz/HEAD/R/2024/week_09/dificultades.csv
--------------------------------------------------------------------------------
/R/30DayChartChallenge2024/day_18/KIDB.xlsx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/michal0091/dataviz/HEAD/R/30DayChartChallenge2024/day_18/KIDB.xlsx
--------------------------------------------------------------------------------
/R/30DayChartChallenge2025/data/day_1.csv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/michal0091/dataviz/HEAD/R/30DayChartChallenge2025/data/day_1.csv
--------------------------------------------------------------------------------
/R/30DayChartChallenge2025/data/day_4.csv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/michal0091/dataviz/HEAD/R/30DayChartChallenge2025/data/day_4.csv
--------------------------------------------------------------------------------
/R/30DayChartChallenge2025/data/ipca_mensual.csv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/michal0091/dataviz/HEAD/R/30DayChartChallenge2025/data/ipca_mensual.csv
--------------------------------------------------------------------------------
/R/30DayChartChallenge2024/theme/fa-brands-400.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/michal0091/dataviz/HEAD/R/30DayChartChallenge2024/theme/fa-brands-400.ttf
--------------------------------------------------------------------------------
/R/30DayChartChallenge2024/theme/fa-solid-900.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/michal0091/dataviz/HEAD/R/30DayChartChallenge2024/theme/fa-solid-900.ttf
--------------------------------------------------------------------------------
/R/30DayChartChallenge2025/data/epa_paro_ccaa.csv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/michal0091/dataviz/HEAD/R/30DayChartChallenge2025/data/epa_paro_ccaa.csv
--------------------------------------------------------------------------------
/R/30DayChartChallenge2025/data/ipv_trimestral.csv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/michal0091/dataviz/HEAD/R/30DayChartChallenge2025/data/ipv_trimestral.csv
--------------------------------------------------------------------------------
/R/30DayChartChallenge2025/data/salario_modal.csv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/michal0091/dataviz/HEAD/R/30DayChartChallenge2025/data/salario_modal.csv
--------------------------------------------------------------------------------
/R/30DayChartChallenge2024/day_14/no2_calendar_data.csv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/michal0091/dataviz/HEAD/R/30DayChartChallenge2024/day_14/no2_calendar_data.csv
--------------------------------------------------------------------------------
/R/30DayChartChallenge2025/data/Distritos/DISTRITOS.sbn:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/michal0091/dataviz/HEAD/R/30DayChartChallenge2025/data/Distritos/DISTRITOS.sbn
--------------------------------------------------------------------------------
/R/30DayChartChallenge2025/data/Distritos/DISTRITOS.sbx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/michal0091/dataviz/HEAD/R/30DayChartChallenge2025/data/Distritos/DISTRITOS.sbx
--------------------------------------------------------------------------------
/R/30DayChartChallenge2024/day_08/pm10_mean_zona_2001.RDS:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/michal0091/dataviz/HEAD/R/30DayChartChallenge2024/day_08/pm10_mean_zona_2001.RDS
--------------------------------------------------------------------------------
/R/30DayChartChallenge2024/day_03/Public_Awareness_Around_Antibiotic_Resistance.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/michal0091/dataviz/HEAD/R/30DayChartChallenge2024/day_03/Public_Awareness_Around_Antibiotic_Resistance.png
--------------------------------------------------------------------------------
/R/30DayChartChallenge2024/day_22/rail_passengers.csv:
--------------------------------------------------------------------------------
1 | year;rail_passengers
2 | 2015;375.713
3 | 2016;384.335
4 | 2017;394.142
5 | 2018;400.427
6 | 2019;413.923
7 | 2020;223.668
8 | 2021;260.715
9 | 2022;393.376
10 |
--------------------------------------------------------------------------------
/dataviz.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 |
--------------------------------------------------------------------------------
/R/2024/week_07/README.md:
--------------------------------------------------------------------------------
1 | # dataviz: week 7
2 |
3 |
4 |
--------------------------------------------------------------------------------
/R/2024/week_08/README.md:
--------------------------------------------------------------------------------
1 | # dataviz: week 8
2 |
3 |
4 |
--------------------------------------------------------------------------------
/R/2024/week_01/README.md:
--------------------------------------------------------------------------------
1 | # dataviz 2024: week 1
2 |
3 |
4 |
--------------------------------------------------------------------------------
/R/2024/week_03/README.md:
--------------------------------------------------------------------------------
1 | # dataviz: week 3
2 |
3 |
4 |
--------------------------------------------------------------------------------
/R/2024/week_05/README.md:
--------------------------------------------------------------------------------
1 | # dataviz: week 5
2 |
3 |
4 |
--------------------------------------------------------------------------------
/R/2024/week_02/README.md:
--------------------------------------------------------------------------------
1 | # dataviz: week 2
2 |
3 |
4 |
--------------------------------------------------------------------------------
/R/2024/week_04/README.md:
--------------------------------------------------------------------------------
1 | # dataviz: week 4
2 |
3 |
4 |
--------------------------------------------------------------------------------
/R/2024/week_10/README.md:
--------------------------------------------------------------------------------
1 | # dataviz 2024: week 10
2 |
3 |
4 |
--------------------------------------------------------------------------------
/R/2024/week_11/README.md:
--------------------------------------------------------------------------------
1 | # dataviz 2024: week 11
2 |
3 |
4 |
--------------------------------------------------------------------------------
/R/2024/week_06/README.md:
--------------------------------------------------------------------------------
1 | # dataviz: week 6
2 |
3 |
4 |
--------------------------------------------------------------------------------
/R/2024/week_12/README.md:
--------------------------------------------------------------------------------
1 | # dataviz 2024: week 12
2 |
3 |
4 |
--------------------------------------------------------------------------------
/R/2024/week_09/README.md:
--------------------------------------------------------------------------------
1 | # dataviz 2024: week 9
2 |
3 |
4 |
--------------------------------------------------------------------------------
/R/30DayChartChallenge2024/day_02/death-rates-from-energy-production-per-twh.csv:
--------------------------------------------------------------------------------
1 | Entity,Code,Year,Deaths per TWh of electricity production
2 | Biomass,,2021,4.63
3 | Brown coal,,2021,32.72
4 | Coal,,2021,24.62
5 | Gas,,2021,2.821
6 | Hydropower,,2021,1.3
7 | Nuclear,,2021,0.03
8 | Oil,,2021,18.43
9 | Solar,,2021,0.019
10 | Wind,,2021,0.035
--------------------------------------------------------------------------------
/R/2024/week_01/eolica.csv:
--------------------------------------------------------------------------------
1 | CCAA,2012,2022
2 | Castilla y León,11350,13796
3 | Aragón,4447,10200
4 | Galicia,8066,9720
5 | Castilla La-Mancha,7944,8360
6 | Andalucía,5731,6980
7 | Navarra,2678,3203
8 | Cataluña,2647,2455
9 | Comunidad Valenciana,2548,1995
10 | Asturias,883,1422
11 | Canarias,362,1369
12 | La Rioja,1006,849
13 | Región de Murcia,401,410
14 | País Vasco,340,320
15 | Extremadura,0,123
16 | Cantabria,62,79
17 | Islas Baleares,6,2
18 | Comunidad de Madrid,0,0
19 |
--------------------------------------------------------------------------------
/R/2024/week_02/eco_farms_poland.csv:
--------------------------------------------------------------------------------
1 | NAME_1,farms,eco_farms
2 | Dolnośląskie,55993,761
3 | Kujawsko-Pomorskie,63830,420
4 | Łódzkie,179994,1926
5 | Lubelskie,20236,1139
6 | Lubuskie,124032,538
7 | Małopolskie,139923,634
8 | Mazowieckie,212917,2393
9 | Opolskie,26919,74
10 | Podkarpackie,132851,886
11 | Podlaskie,81181,4047
12 | Pomorskie,39049,586
13 | Śląskie,54503,139
14 | Świętokrzyskie,85308,571
15 | Warmińsko-Mazurskie,43165,3654
16 | Wielkopolskie,121157,848
17 | Zachodniopomorskie,29646,2577
18 |
--------------------------------------------------------------------------------
/R/30DayChartChallenge2024/day_13/storks.csv:
--------------------------------------------------------------------------------
1 | Country,Area,Storks,Humans,Birth
2 | Albania,28750,100,3.2,83
Austria,83860,300,7.6,87
Belgium,30520,1,9.9,118
Bulgaria,111000,5000,9.0,117
Denmark,43100,9,5.1,59
France,544000,140,56,774
Germany,357000,3300,78,901
Greece,132000,2500,10,106
Holland,41900,4,15,188
Hungary,93000,5000,11,124
Italy,301280,5,57,551
Poland,312680,30000,38,610
Portugal,92390,1500,10,120
Romania,237500,5000,23,367
Spain,504750,8000,39,439
Switzerland,41290,150,6.7,82
Turkey,779450,25000,56,1576
--------------------------------------------------------------------------------
/R/30DayChartChallenge2024/day_10/physical.csv:
--------------------------------------------------------------------------------
1 | date;position;week;year
2 | 1981-10-03;66;1;1981
3 | 1981-10-10;47;2;1981
4 | 1981-10-17;31;3;1981
5 | 1981-10-24;26;4;1981
6 | 1981-10-31;23;5;1981
7 | 1981-11-07;14;6;1981
8 | 1981-11-14;3;7;1981
9 | 1981-11-21;1;8;1981
10 | 1981-11-28;1;9;1981
11 | 1981-12-05;1;10;1981
12 | 1981-12-12;1;11;1981
13 | 1981-12-19;1;12;1981
14 | 1981-12-26;1;13;1981
15 | 1982-01-02;1;14;1982
16 | 1982-01-09;1;15;1982
17 | 1982-01-16;1;16;1982
18 | 1982-01-23;1;17;1982
19 | 1982-01-30;4;18;1982
20 | 1982-02-06;7;19;1982
21 | 1982-02-13;8;20;1982
22 | 1982-02-20;9;21;1982
23 | 1982-02-27;17;22;1982
24 | 1982-03-06;31;23;1982
25 | 1982-03-13;46;24;1982
26 | 1982-03-20;56;25;1982
27 | 1982-03-27;95;26;1982
28 |
--------------------------------------------------------------------------------
/R/30DayChartChallenge2024/day_27/forecast.csv:
--------------------------------------------------------------------------------
1 | previsiones;pib_2024;pib_2025
2 | Analistas Financieros Internacionales (AFI);1,8;1,8
3 | BBVA Research;2,1;2
4 | CaixaBank Research;1,9;2,2
5 | Cámara de Comercio de España;2;1,9
6 | Centro de Estudios Economía de Madrid (CEEM-URJC);1,9;2,3
7 | Centro de Predicción Económica (CEPREDE-UAM);2,1;2,4
8 | CEOE;1,8;2
9 | Equipo Económico (Ee);2,1;2
10 | EthiFinance Ratings;1,9;2
11 | Funcas;1,8;2
12 | Instituto Complutense de Análisis Económico (ICAE-UCM);2,1;2
13 | Instituto de Estudios Económicos (IEE);1,7;1,9
14 | Intermoney;1,8;1,7
15 | Mapfre Economics;1,4;1,8
16 | Metyis;2;2
17 | Oxford Economics;2,1;1,7
18 | Repsol;1,5;2,3
19 | Santander;1,8;2
20 | Universidad Loyola Andalucía;1,8;1,5
21 |
--------------------------------------------------------------------------------
/R/30DayChartChallenge2024/day_21/energy.csv:
--------------------------------------------------------------------------------
1 | year;Portugal;Italy;Greece;Spain;EU27
2 | 2004;27,39;16,086;7,842;19,018;15,871
3 | 2005;27,703;16,293;8,213;19,166;16,402
4 | 2006;29,308;15,926;8,924;20,027;16,879
5 | 2007;32,285;15,954;9,33;21,718;17,647
6 | 2008;34,063;16,645;9,646;23,777;18,526
7 | 2009;37,562;18,807;11,016;27,882;20,654
8 | 2010;40,608;20,091;12,307;29,748;21,283
9 | 2011;45,78;23,546;13,81;31,53;23,3
10 | 2012;47,505;27,42;16,364;33,438;25,138
11 | 2013;49,101;31,302;21,241;36,027;26,769
12 | 2014;52,054;33,42;21,923;37,128;28,601
13 | 2015;52,616;33,459;22,089;36,972;29,655
14 | 2016;53,99;34,012;22,657;36,676;30,172
15 | 2017;54,168;34,104;24,464;36,465;31,104
16 | 2018;52,186;33,93;26,001;35,236;32,134
17 | 2019;53,774;34,969;31,295;37,131;34,086
18 | 2020;58,032;38,081;35,856;42,944;37,408
19 | 2021;58,433;35,996;35,934;46,001;37,754
20 | 2022;60,959;37,102;42,408;50,902;41,174
21 |
--------------------------------------------------------------------------------
/R/2024/week_47/forecast_11_2024.csv:
--------------------------------------------------------------------------------
1 | previsiones;pib_2024_04_2024;pib_2025_04_2024;pib_2024_11_2024;pib_2025_11_2024
2 | Analistas Financieros Internacionales (AFI);1,8;1,8;3,1;2,6
3 | BBVA Research;2,1;2;2,9;2,4
4 | CaixaBank Research;1,9;2,2;2,8;2,3
5 | Cámara de Comercio de España;2;1,9;3,1;2,1
6 | Centro de Estudios Economía de Madrid (CEEM-URJC);1,9;2,3;3,2;3,1
7 | Centro de Predicción Económica (CEPREDE-UAM);2,1;2,4;3;2,3
8 | CEOE;1,8;2;3,1;2,3
9 | Equipo Económico (Ee);2,1;2;3,1;2,2
10 | EthiFinance Ratings;1,9;2;3;2,3
11 | Funcas;1,8;2;3;2,1
12 | Instituto Complutense de Análisis Económico (ICAE-UCM);2,1;2;3;2,4
13 | Instituto de Estudios Económicos (IEE);1,7;1,9;3;2,1
14 | Intermoney;1,8;1,7;2,9;2,1
15 | Mapfre Economics;1,4;1,8;2,9;2,1
16 | Metyis;2;2;3,1;2,4
17 | Oxford Economics;2,1;1,7;3,1;2,4
18 | Repsol;1,5;2,3;3;2,3
19 | Santander;1,8;2;2,9;2,4
20 | Universidad Loyola Andalucía;1,8;1,5;2,9;2,5
21 |
--------------------------------------------------------------------------------
/R/2024/week_05/salarios.csv:
--------------------------------------------------------------------------------
1 | id,country,gross,net,coin,city,rental_one_bedroom,pe
2 | UK,United Kingdom,40518,32733,"1,1589",London,1800,"0,65988"
3 | FR,France,30833,24144,1,Paris,1880,"0,93439"
4 | ES,Spain,21638,17559,1,Madrid,1350,"0,9226"
5 | DE,Germany,43842,28128,1,Berlin,1600,"0,68259"
6 | IT,Italy,25000,20000,1,Rome,1950,"1,17"
7 | PL,Poland,15162,11214,"0,2216",Warsaw,730,"0,78117"
8 | NL,Netherlands,44000,35092,1,Amsterdam,2300,"0,7865"
9 | SE,Sweden,36250,25628,"0,088329",Stockholm,1325,"0,62042"
10 | BE,Belgium,42084,33796,1,Brussels,1200,"0,42609"
11 | NO,Norway,49656,32957,"0,086787",Oslo,1300,"0,47334"
12 | IE,Ireland,45537,36513,1,Dublin,1650,"0,54227"
13 | AT,Austria,30635,20381,1,Vienna,1200,"0,70654"
14 | DK,Danmark,37411,25253,"0,13409",Copenhagen,1200,"0,57023"
15 | RO,Romania,19618,11477,"0,20109",Bucharest,400,"0,41823"
16 | FI,Finland,38736,23895,1,Helsinki,1340,"0,67294"
17 | CZ,Czech Republic,16970,13706,"0,040705",Prague,950,"0,83175"
18 | PT,Portugal,11512,10236,1,Lisbon,1300,"1,52403"
19 |
--------------------------------------------------------------------------------
/R/30DayChartChallenge2024/day_18/exchange.csv:
--------------------------------------------------------------------------------
1 | country;exchange_rate;region
2 | Brunei Darussalam;1,40;Southeast Asia
3 | Cambodia;4118,00;Southeast Asia
4 | Indonesia;15731,00;Southeast Asia
5 | Lao People’s Democratic Republic;16600,00;Southeast Asia
6 | Malaysia;4,40;Southeast Asia
7 | Myanmar;1329,10;Southeast Asia
8 | Philippines;56,10;Southeast Asia
9 | Singapore;1,34;Southeast Asia
10 | Thailand;34,56;Southeast Asia
11 | Viet Nam;23612,00;Southeast Asia
12 | Bangladesh;99,00;South Asia
13 | India;82,80;South Asia
14 | Nepal;131,90;South Asia
15 | Pakistan;226,50;South Asia
16 | Sri Lanka;363,10;South Asia
17 | Armenia;393,60;Central and West Asia
18 | Azerbaijan;1,70;Central and West Asia
19 | Georgia;2,70;Central and West Asia
20 | Kazakhstan;462,70;Central and West Asia
21 | Kyrgyz Rep.;85,70;Central and West Asia
22 | Tajikistan;10,20;Central and West Asia
23 | Uzbekistan;11225,50;Central and West Asia
24 | Fiji, Rep. of;2,20;Pacific Islands
25 | Papua New Guinea;3,50;Pacific Islands
26 | Samoa;2,70;Pacific Islands
27 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2024 Michal Kinel
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 |
--------------------------------------------------------------------------------
/R/30DayChartChallenge2024/day_26/ai.csv:
--------------------------------------------------------------------------------
1 | Type;Group;Hardly ever or never;Some of the time or occasionally;Often or always
2 | All;All adults;33;50;17
3 | Sex;Women;38;49;13
4 | Sex;Men;29;50;21
5 | Age;Aged 16 to 29;20;49;31
6 | Age;Aged 30 to 49;27;55;18
7 | Age;Aged 50 to 69;37;51;12
8 | Age;Aged 70 and over;55;36;8
9 | Ethnic group;Asian or Asian British;33;47;20
10 | Ethnic group;Black African Caribbean or Black British;33;42;25
11 | Ethnic group;Mixed or Multiple ethnic groups;20;43;36
12 | Ethnic group;White;34;50;16
13 | Ethnic group;Any other ethnic group;30;57;12
14 | Disabled;Disabled;38;47;15
15 | Disabled;Non-disabled;31;51;18
16 | Degree ;Degree or equivalent;20;58;22
17 | Degree ;No degree;39;46;15
18 | Occupation;Managers directors and senior officials;25;58;17
19 | Occupation;Professional occupations;18;58;24
20 | Occupation;Associate professional occupations;21;59;21
21 | Occupation;Administrative and secretarial occupations;35;52;14
22 | Occupation;Skilled trades occupations;32;51;18
23 | Occupation;Caring leisure and other service occupations;44;46;11
24 | Occupation;Sales and customer service occupations;32;54;14
25 | Occupation;Process plant and machine operatives;36;52;12
26 | Occupation;Elementary occupations;36;46;18
27 |
--------------------------------------------------------------------------------
/R/30DayChartChallenge2024/day_07/hectares_burned_spain.csv:
--------------------------------------------------------------------------------
1 | year,hectares_burned
2 | 1961,46251
3 | 1962,55482
4 | 1963,22679
5 | 1964,31398
6 | 1965,38018
7 | 1966,49354
8 | 1967,76575
9 | 1968,55702
10 | 1969,"53171,6"
11 | 1970,"87438,5"
12 | 1971,"34312,4"
13 | 1972,"55920,1"
14 | 1973,"95072,5"
15 | 1974,"139927,5"
16 | 1975,"180136,9"
17 | 1976,"121514,1"
18 | 1977,"68870,9"
19 | 1978,"424957,9"
20 | 1979,"197655,05"
21 | 1980,"261514,8"
22 | 1981,"291417,1"
23 | 1982,"149077,1"
24 | 1983,107551
25 | 1984,"164166,1"
26 | 1985,"484475,2"
27 | 1986,"264787,4"
28 | 1987,"147340,4"
29 | 1988,"137272,6"
30 | 1989,"407122,1"
31 | 1990,"203641,4"
32 | 1991,260303
33 | 1992,"105277,6"
34 | 1993,"89331,1"
35 | 1994,"437602,5"
36 | 1995,"141082,17"
37 | 1996,"58919,27"
38 | 1997,"98503,17"
39 | 1998,"132892,34"
40 | 1999,"81680,67"
41 | 2000,"187567,06"
42 | 2001,"93297,54"
43 | 2002,"107464,05"
44 | 2003,"148172,47"
45 | 2004,"134192,64"
46 | 2005,"188697,49"
47 | 2006,"155344,83"
48 | 2007,"86122,03"
49 | 2008,"50322,09"
50 | 2009,"120094,21"
51 | 2010,"54769,88"
52 | 2011,"102161,33"
53 | 2012,"218956,59"
54 | 2013,"61690,61"
55 | 2014,"48717,83"
56 | 2015,"109782,85"
57 | 2016,"68121,05"
58 | 2017,"178482,38"
59 | 2018,"23911,89"
60 | 2019,"84060,89"
61 | 2020,"65923,08"
62 | 2023,"66063,51"
63 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # History files
2 | .Rhistory
3 | .Rapp.history
4 |
5 | # Session Data files
6 | .RData
7 | .RDataTmp
8 |
9 | # Plots
10 | *.png
11 | *.svg
12 | *.tiff
13 | *.gif
14 |
15 | # User-specific files
16 | .Ruserdata
17 | *.pdf
18 | *.zip
19 | *.tif
20 | *.ovr
21 | *.rds
22 | *.cpp
23 | *.qs
24 | *.xlsx
25 | *.xls
26 | *.shp
27 | *.shx
28 | *.dbf
29 | *.prj
30 | *.cpg
31 |
32 |
33 |
34 | # Example code in package build process
35 | *-Ex.R
36 |
37 | # Output files from R CMD build
38 | /*.tar.gz
39 |
40 | # Output files from R CMD check
41 | /*.Rcheck/
42 |
43 | # RStudio files
44 | .Rproj.user/
45 |
46 | # produced vignettes
47 | vignettes/*.html
48 | vignettes/*.pdf
49 |
50 | # OAuth2 token, see https://github.com/hadley/httr/releases/tag/v0.3
51 | .httr-oauth
52 |
53 | # knitr and R markdown default cache directories
54 | *_cache/
55 | /cache/
56 |
57 | # Temporary files created by R markdown
58 | *.utf8.md
59 | *.knit.md
60 |
61 | # R Environment Variables
62 | .Renviron
63 |
64 | # pkgdown site
65 | docs/
66 |
67 | # translation temp files
68 | po/*~
69 |
70 | # RStudio Connect folder
71 | rsconnect/
72 | R/30DayChartChallenge2025/data/poblacion_municipios_ine.csv
73 | R/30DayChartChallenge2025/data/pand-c-shp/pand_c.shp.xml
74 | R/30DayChartChallenge2025/data/pand-p-shp/pand_p.shp.xml
75 |
--------------------------------------------------------------------------------
/R/2024/week_10/gender_pay_gap_2022.csv:
--------------------------------------------------------------------------------
1 | country;employment_F;wanting_work_care_F;F_manager;gender_pay_gap_2012;gender_pay_gap_2022
2 | European Union - 27 countries (from 2020);69,3;18,5;35,0604757036208;16,4;12,7
3 | Belgium;68,1;8,7;36,377789309808;8,3;5
4 | Bulgaria;71,8;10,7;40,8492822966507;15,1;13
5 | Czechia;73,7;27,3;26,8246802106847;22,5;17,9
6 | Denmark;77,4;4,9;29,2326431181486;16,8;13,9
7 | Germany;76,8;25,4;28,9057162377591;22,7;17,7
8 | Estonia;80,4;18,2;40,2298850574713;29,9;21,3
9 | Ireland;72,6;30,4;38,1894736842105;12,2;9,3
10 | Spain;64,1;20,2;34,7131608548931;18,7;8,7
11 | France;71,2;17,6;39,8867474667197;15,6;13,9
12 | Italy;55;14,8;27,8745242763234;6,5;4,3
13 | Cyprus;72,1;29,1;22,8070175438596;15,6;10,2
14 | Latvia;75,5;;45,0110864745011;14,9;17,1
15 | Lithuania;78,6;17,1;38,5832705350415;11,9;12
16 | Luxembourg;71,5;12,3;25,531914893617;7;-0,7
17 | Hungary;75,3;20,7;37,5423318819545;20,1;17,5
18 | Malta;74,1;;33,6391437308869;9,5;10,2
19 | Netherlands;79;9,6;28,4187611320008;18;13
20 | Austria;73,4;21,6;33,4353146853147;22,9;18,4
21 | Poland;70,2;32;42,9086321859795;6,4;7,8
22 | Portugal;74,3;16,1;36,7416496250852;15;12,5
23 | Romania;59,1;11,3;33,0387205387205;6,9;4,5
24 | Slovenia;74,3;19,7;34,7721822541966;4,5;8,2
25 | Slovakia;72,6;25,3;38,0405405405405;20,8;17,7
26 | Finland;77,8;;36,2876254180602;19,2;15,5
27 | Sweden;79,2;3,8;41,6642250219748;15,5;11,1
28 | Iceland;82,1;;39,5522388059702;17,7;9,3
29 | Norway;78;;33,1745344304894;14,7;14,4
30 | Switzerland;77,8;22;30,6666666666667;17,4;17,9
31 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # :chart_with_upwards_trend: dataviz
2 | Repositorio de GitHub con scripts de visualizaciones de datos en R. Incluye gráficos de barras, líneas, dispersión, anillos, mapas, árboles, burbujas, caja y probabilidad.
3 |
4 | :star: Incluye gráficos de barras, líneas, dispersión, anillos, mapas, árboles, burbujas, caja y probabilidad.
5 |
6 | :pencil: Los scripts están documentados y fáciles de usar.
7 |
8 |
9 | ## :point_up: Antes de nada...
10 | Para el fastidio de muchos suelo utilizar fuentes personalizadas para los gráficos.
11 | La fuente que suelo usar es la Lato disponible en las fonts de Google:
12 | * Para descargar: [font Lato](https://fonts.google.com/specimen/Lato)
13 | * Para instalar basata con descargar la familia, desempaquetar el .zip e instalar una apriendo los ficheros
14 | * Las variantes que más uso: `"Lato-Regular"` y `"Lato-Black"`
15 |
16 |
17 | Para instalar las fuentes del pc (windows) en R:
18 |
19 | ```{r}
20 | # Install
21 | install.packages("extrafont")
22 | library(extrafont)
23 |
24 | # Load fonts
25 | font_import()
26 | loadfonts(device = "win")
27 | ```
28 |
29 |
30 | ## :deciduous_tree: Estructura del proyecto
31 |
32 | ```
33 | 📦 scouting
34 | ┣ 📂 R # R scripts
35 | ┃ ┗ 📂 2024 # R scripts of data visualizations in 2024
36 | ┃ ┗ 📂 week_01 # R script of visualization of the first week
37 | ┃ ┣ 📜 2024_w01_lollipop_eolica.R # R R script thats makes a 🍭 lollipop plot of eolica data
38 | ┃ ┗ 📄 eolica.csv # Input data csv file
39 | ┣ 📜 .gitignore
40 | ┣ 📜 README.md
41 | ┣ 📜 dataviz.Rproj # R project file
42 |
43 | ```
44 |
45 | ## :raised_hands: Contribuciones
46 |
47 | :fire: Se aceptan contribuciones al repositorio. Si tiene un script de visualización de datos en R que desea compartir, envíe un pull request.
48 |
49 | ## :postbox: Contacto
50 | Si tiene alguna pregunta o comentario, envíe un correo electrónico al propietario del repositorio.
51 | * :mailbox: michal.kinel@gmail.com
52 | * :octocat: [michal0091](https://github.com/michal0091)
53 |
54 | ## :copyright: Licencia
55 |
56 | :copyright: El repositorio está licenciado bajo la licencia MIT.
57 |
58 |
--------------------------------------------------------------------------------
/R/2024/week_12/portfolio.csv:
--------------------------------------------------------------------------------
1 | name,type,prp
2 | Alemania,pais,"4,372148448"
3 | Arabia Saudita,pais,"0,3375508149"
4 | Australia,pais,"0,234917192"
5 | Austria,pais,"0,1016591076"
6 | Bélgica,pais,"0,4120039073"
7 | Brasil,pais,"0,4068816801"
8 | Bulgaria,pais,"0,001184502868"
9 | Canadá,pais,"0,8619165035"
10 | Chile,pais,"0,04379179984"
11 | China,pais,"2,764477935"
12 | Colombia,pais,"0,0218709575"
13 | Corea,pais,"1,141961732"
14 | Croacia,pais,"0,001184502868"
15 | Dinamarca,pais,"1,355408731"
16 | Egipto,pais,"0,004872587419"
17 | Emiratos Árabes Unidos,pais,"0,09314066893"
18 | Eslovaquia,pais,"0,008291520076"
19 | Eslovenia,pais,"0,003553508604"
20 | España,pais,"1,127079558"
21 | Estados Unidos,pais,"57,98013063"
22 | Filipinas,pais,"0,04573387355"
23 | Finlandia,pais,"0,8351356396"
24 | Francia,pais,"4,429582331"
25 | Grecia,pais,"0,05159490097"
26 | Holanda,pais,"1,89650863"
27 | Hong Kong,pais,"0,004249592521"
28 | Hungría,pais,"0,02618203695"
29 | India,pais,"1,213970351"
30 | Indonesia,pais,"0,1774863203"
31 | Irlanda,pais,"0,8627923663"
32 | Israel,pais,"0,2992389537"
33 | Italia,pais,"1,299739458"
34 | Japón,pais,"3,789414435"
35 | Kuwait,pais,"0,06473580428"
36 | Letonia,pais,"0,001184502868"
37 | Lituania,pais,"0,001184502868"
38 | Luxemburgo,pais,"0,003553508604"
39 | Malasia,pais,"0,1400938516"
40 | México,pais,"0,237899443"
41 | Noruega,pais,"0,2670045634"
42 | Nueva Zelanda,pais,"0,02013654876"
43 | Panamá,pais,"0,002369005736"
44 | Perú,pais,"0,02819719968"
45 | Polonia,pais,"0,1297251362"
46 | Portugal,pais,"0,05113435198"
47 | Qatar,pais,"0,06975456974"
48 | Reino Unido,pais,"5,16994458"
49 | República Checa,pais,"0,02243246547"
50 | Rumania,pais,"0,01421403442"
51 | Singapur,pais,"0,02724356596"
52 | Sudáfrica,pais,"0,2018643359"
53 | Suecia,pais,"1,544253649"
54 | Suiza,pais,"3,148179924"
55 | Supranacional,pais,"0,2369005736"
56 | Tailandia,pais,"0,1638952807"
57 | Taiwán,pais,"2,09743001"
58 | Turquía,pais,"0,06125538469"
59 | Unión Europea,pais,"0,08857353032"
60 | Uruguay,pais,"0,001184502868"
61 | Bonos públicos,sector,"1,756699681"
62 | Bonos privados,sector,"1,088573874"
63 | Bonos del Tesoro,sector,"6,512112299"
64 | Comunicación,sector,"5,591839005"
65 | Consumo discrecional,sector,"8,648230778"
66 | Cuidado de la Salud,sector,"9,941197779"
67 | Efectivo y Derivados,sector,"1,240863219"
68 | Energía,sector,"2,160674863"
69 | Financieros,sector,"12,04559344"
70 | Industriales,sector,"11,67572367"
71 | Inmobiliario,sector,"1,470909351"
72 | Materiales,sector,"2,809669807"
73 | Productos básicos de consumo,sector,"3,158536105"
74 | Servicios,sector,"1,431206743"
75 | Tecnología de la Información,sector,"30,46816939"
--------------------------------------------------------------------------------
/R/2024/week_49/2024_w47.R:
--------------------------------------------------------------------------------
1 | # Libraries ---------------------------------------------------------------
2 | library(data.table)
3 | library(tidyverse)
4 | library(ggforce)
5 | library(ggtext)
6 | library(ggrepel)
7 | library(emojifont)
8 | library(sysfonts)
9 | library(showtext)
10 | library(ggplot2)
11 | library(tidyverse)
12 | library(mlmhelpr)
13 | library(sysfonts)
14 | library(showtext)
15 |
16 |
17 | # Source ------------------------------------------------------------------
18 | source("R/30DayChartChallenge2024/theme/styles.R")
19 | source("R/30DayChartChallenge2024/theme/theme.R")
20 |
21 | # Font Awesome
22 | font_add(family = "fa-brands", regular = "fonts/fa-brands-400.ttf")
23 | showtext_auto()
24 |
25 | # Functions ---------------------------------------------------------------
26 | new_caption_text <- function(viz_author = "Michal Kinel",
27 | source_text,
28 | color_text_1 = "#352725",
29 | color_text_2 = "#3f68e3",
30 | github_icon = '',
31 | github_username = "michal0091",
32 | twitter_icon = "",
33 | twitter_username = "nico_kinel",
34 | linkedin_icon = "",
35 | linkedin_username = "michal-kinel",
36 | bluesky_icon = "",
37 | bluesky_username = "mikipe",
38 | bluesky_server = "bsky.sociall") {
39 |
40 | social_caption <- glue::glue(
41 | "
42 | Data Visualization: {viz_author}
43 | Source: {source_text}
44 | {github_icon};
45 | {github_username}
46 | {twitter_icon};
47 | {twitter_username}
48 | {linkedin_icon};
49 | {linkedin_username}
50 | {bluesky_icon};
51 | {bluesky_username}.{bluesky_server}
52 | "
53 | )
54 |
55 | social_caption
56 |
57 | }
58 |
59 |
60 | # Data --------------------------------------------------------------------
--------------------------------------------------------------------------------
/R/30DayChartChallenge2024/day_13/day_13_family.R:
--------------------------------------------------------------------------------
1 | # 30DayChartChallenge2024 / day_13_family
2 |
3 | # Libraries ---------------------------------------------------------------
4 | library(data.table)
5 | library(tidyverse)
6 | library(ggforce)
7 | library(ggtext)
8 | library(ggrepel)
9 | library(emojifont)
10 | library(sysfonts)
11 | library(showtext)
12 | library(patchwork)
13 |
14 | # Source ------------------------------------------------------------------
15 | source("R/30DayChartChallenge2024/theme/styles.R")
16 | source("R/30DayChartChallenge2024/theme/theme.R")
17 |
18 |
19 | # Config ------------------------------------------------------------------
20 | cfg <-
21 | yaml::read_yaml("R/30DayChartChallenge2024/cfg/plots.yml")[["default"]]
22 | cfg_day_13 <- cfg$day_13
23 |
24 |
25 | # Data --------------------------------------------------------------------
26 | storks <- read.csv("R/30DayChartChallenge2024/day_13/storks.csv") %>%
27 | as.data.table()
28 |
29 |
30 | # Plot --------------------------------------------------------------------
31 |
32 | plot <- storks[, ggplot(.SD, aes(x = Storks, y = Birth)) +
33 | geom_smooth(method = "lm", color = c3_color_accent_1, se = FALSE) +
34 | geom_point(color = c3_color_accent_2, size = 2) +
35 | scale_x_log10() +
36 | scale_y_log10() +
37 | # Add correlation label
38 | geom_text(
39 | aes(x = 20000, y = 220, label = paste0("Correlation: ", round(cor(Storks, Birth), 3))),
40 | family = "redhat_light",
41 | color = c3_color_text_1,
42 | size = rel(6),
43 | hjust = 1,
44 | vjust = 1
45 | ) +
46 | labs(
47 | title = "Storks Deliver Babies?",
48 | subtitle = "Correlation is not causation",
49 | x = "Number of storks breeding pairs",
50 | y = "Birth rate (thousands per year)",
51 | caption = caption_text(
52 | source_text = cfg_day_13$source,
53 | day_type = cfg_day_13$category,
54 | day_hashtag = cfg_day_13$theme,
55 | day = cfg_day_13$day,
56 | color_text_1 = c3_color_text_2,
57 | color_text_2 = c3_color_text_1
58 | )
59 | ) +
60 | theme_my(
61 | font_regular = "redhat_regular",
62 | font_bold = "redhat_bold",
63 | font_light = "redhat_light",
64 | color_text_1 = c3_color_text_2,
65 | color_text_2 = c3_color_text_1,
66 | color_background = c3_color_background,
67 | title_size = 36
68 | ) +
69 | theme(
70 | plot.margin = margin(25, 5, 5, 10, "pt"),
71 | plot.caption = element_textbox_simple(
72 | size = 13,
73 | lineheight = .5,
74 | padding = margin(5, 5, 5, 5, "pt"),
75 | margin = margin(10, 0, 0, 0, "pt"),
76 | ))]
77 |
78 |
79 | # Save --------------------------------------------------------------------
80 | ggsave(
81 | filename = "day_13_family.png",
82 | path = normalizePath("R/30DayChartChallenge2024/day_13"),
83 | plot = plot,
84 | device = "png",
85 | units = "px",
86 | width = 1080,
87 | height = 1080,
88 | dpi = 320
89 | )
90 |
--------------------------------------------------------------------------------
/R/30DayChartChallenge2024/day_07/day_7_hazards.R:
--------------------------------------------------------------------------------
1 | # 30DayChartChallenge2024 / day_7_hazards
2 |
3 | # Libraries ---------------------------------------------------------------
4 | library(data.table)
5 | library(ggplot2)
6 | library(ggforce)
7 | library(ggtext)
8 | library(emojifont)
9 | library(sysfonts)
10 | library(showtext)
11 | library(patchwork)
12 |
13 |
14 | # Source ------------------------------------------------------------------
15 | source("R/30DayChartChallenge2024/theme/styles.R")
16 | source("R/30DayChartChallenge2024/theme/theme.R")
17 |
18 |
19 | # Config ------------------------------------------------------------------
20 | cfg <-
21 | yaml::read_yaml("R/30DayChartChallenge2024/cfg/plots.yml")[["default"]]
22 | cfg_day_7 <- cfg$day_7
23 |
24 |
25 | #'Métrica":"Hectáreas quemadas
26 | #'Fuente":"Ministerio de Agricultura y Pesca, Alimentación y Medio Ambiente
27 | #'Clasificación":" "Unidad":"Hectáreas afectadas
28 | #'Escala":"Unidades
29 |
30 |
31 | # Data --------------------------------------------------------------------
32 | hbs <- read.csv("R/30DayChartChallenge2024/day_07/hectares_burned_spain.csv",
33 | dec = ",") %>%
34 | as.data.table()
35 |
36 |
37 | # Plot --------------------------------------------------------------------
38 | plot <- hbs[, ggplot(.SD, aes(hectares_burned)) +
39 | geom_histogram(bins = round(sqrt(.N)), fill = c2_color_accent_2,
40 | color = c2_color_accent_2) +
41 | scale_x_continuous(labels = scales::comma) +
42 | scale_y_continuous(breaks = seq(0, 30, 5), limits = c(0, 30)) +
43 | labs(
44 | title = "Wildfires in Spain",
45 | subtitle = "Number of hectares burned between 1961 and 2023",
46 | x = "ha burned",
47 | y = "Frequency",
48 | caption = caption_text(
49 | source_text = cfg_day_7$source,
50 | day_type = cfg_day_7$category,
51 | day_hashtag = cfg_day_7$theme,
52 | day = cfg_day_7$day,
53 | color_text_1 = c2_color_text_1,
54 | color_text_2 = c2_color_text_2
55 | )
56 | ) +
57 | theme_my(font_regular = "roboto_regular",
58 | font_bold = "roboto_bold",
59 | font_light = "roboto_light",
60 | color_text_1 = c2_color_text_1,
61 | color_text_2 = c2_color_text_2,
62 | color_background = c2_color_background,
63 | title_size = 30) +
64 | theme(plot.margin = margin(25, 5, 5, 5, "pt"))
65 | ]
66 |
67 |
68 | # Save --------------------------------------------------------------------
69 | ggsave(
70 | filename = "day_7_hazards.png",
71 | path = normalizePath("R/30DayChartChallenge2024/day_07"),
72 | plot = plot,
73 | device = "png",
74 | units = "px",
75 | width = 1080,
76 | height = 1080,
77 | dpi = 320
78 | )
79 |
--------------------------------------------------------------------------------
/R/30DayChartChallenge2024/day_29/day_29_black_n_white.R:
--------------------------------------------------------------------------------
1 | # 30DayChartChallenge2024 / day_29_black_n_white
2 |
3 | # Libraries ---------------------------------------------------------------
4 | library(data.table)
5 | library(tidyverse)
6 | library(primes)
7 |
8 |
9 | # Source ------------------------------------------------------------------
10 | source("R/30DayChartChallenge2024/theme/styles.R")
11 | source("R/30DayChartChallenge2024/theme/theme.R")
12 |
13 |
14 | # Config ------------------------------------------------------------------
15 | cfg <-
16 | yaml::read_yaml("R/30DayChartChallenge2024/cfg/plots.yml")[["default"]]
17 | cfg_day_29 <- cfg$day_29
18 |
19 |
20 | # Data --------------------------------------------------------------------
21 |
22 | # Prime numbers
23 | set.seed(16011991)
24 | n <- 365
25 | r <- 2000
26 |
27 | random <- function(n) {
28 | if (is_prime(n)) return(n / 2)
29 | return(2 * n - 1)
30 | }
31 | dt <- data.table(x = rep(1:n, r),
32 | y = as.vector(replicate(r, cumsum(
33 | sapply(sample(1:30, n, TRUE), random) * sample(c(-1, 1), n, TRUE)
34 | ))),
35 | id = rep(1:r, each = n))
36 |
37 | # Plot --------------------------------------------------------------------
38 |
39 | plot <- ggplot(dt, aes(x = x, y = y, group = id)) +
40 | geom_line(color = "white", alpha = 0.03) +
41 | scale_x_continuous(expand = c(0, 0)) +
42 | labs(
43 | title = "Random walk simulation",
44 | subtitle = "2.000 random walks using prime numbers as a rule\nif n is prime, n/2, otherwise 2n-1",
45 | caption = caption_text(
46 | source_text = cfg_day_29$source,
47 | day_type = cfg_day_29$category,
48 | day_hashtag = cfg_day_29$theme,
49 | day = cfg_day_29$day,
50 | color_text_1 = "white",
51 | color_text_2 = "white"
52 | )
53 | ) +
54 | theme_void() +
55 | theme(
56 | plot.margin = margin(35, 0, 0, 0, "pt"),
57 | plot.background = element_rect(fill = "black"),
58 | panel.background = element_rect(fill = "black"),
59 | plot.title = element_text(
60 | size = 56,
61 | family = "roboto_bold",
62 | color = "white",
63 | face = "bold",
64 | hjust = 0,
65 | vjust = 4.5,
66 | lineheight = .34,
67 | margin = margin(5, 5, 5, 35, "pt")
68 | ),
69 | plot.subtitle = element_text(
70 | size = 42,
71 | family = "roboto_bold",
72 | color = "white",
73 | hjust = 0,
74 | vjust = 3,
75 | lineheight = .3,
76 | margin = margin(5, 5, 5, 35, "pt")
77 | ),
78 | plot.caption = element_textbox_simple(
79 | size = 26,
80 | lineheight = .5,
81 | padding = margin(3, 3, 3, 3, "pt"),
82 | margin = margin(15, 10, 15, 35, "pt"),
83 | ),
84 | plot.title.position = "plot",
85 | plot.caption.position = "plot"
86 | )
87 |
88 |
89 |
90 | # Save --------------------------------------------------------------------
91 | ggsave(
92 | "R/30DayChartChallenge2024/day_29/day_29_black_n_white.png",
93 | plot,
94 | width = 1920,
95 | height = 1920,
96 | units = "px",
97 | dpi = 320, limitsize = F
98 | )
99 |
--------------------------------------------------------------------------------
/R/30DayChartChallenge2024/day_17/day_17_networks.R:
--------------------------------------------------------------------------------
1 | # 30DayChartChallenge2024 / day_17_networks
2 |
3 | # Libraries ---------------------------------------------------------------
4 | library(data.table)
5 | library(tidyverse)
6 | library(ggforce)
7 | library(ggtext)
8 | library(ggrepel)
9 | library(emojifont)
10 | library(sysfonts)
11 | library(showtext)
12 | library(patchwork)
13 | library(lubridate)
14 | library(geomnet)
15 | library(ggnetwork)
16 | library(igraph)
17 |
18 |
19 | # Source ------------------------------------------------------------------
20 | source("R/30DayChartChallenge2024/theme/styles.R")
21 | source("R/30DayChartChallenge2024/theme/theme.R")
22 |
23 |
24 | # Config ------------------------------------------------------------------
25 | cfg <-
26 | yaml::read_yaml("R/30DayChartChallenge2024/cfg/plots.yml")[["default"]]
27 | cfg_day_17 <- cfg$day_17
28 |
29 |
30 | # Data --------------------------------------------------------------------
31 | blood_igraph <- graph_from_data_frame(d = blood$edges, directed = TRUE)
32 | data <-
33 | ggnetwork(blood.igraph,
34 | layout = layout_in_circle(blood_igraph),
35 | arrow.gap = 0.05)
36 |
37 |
38 | # Plot --------------------------------------------------------------------
39 |
40 | plot <- ggplot(data = data, aes(
41 | x = x,
42 | y = y,
43 | xend = xend,
44 | yend = yend
45 | )) +
46 | geom_edges(
47 | linewidth = 0.5,
48 | curvature = 0.05,
49 | colour = c3_color_text_2,
50 | arrow = arrow(length = unit(2, "pt"), type = "closed", angle = 25)
51 | ) +
52 | geom_nodes(color = c3_color_accent_1,
53 | size = 4,
54 | show.legend = FALSE) +
55 | geom_nodetext(
56 | aes(label = name),
57 | color = c3_color_text_1,
58 | family = "redhat_bold",
59 | fontface = "bold",
60 | show.legend = FALSE,
61 | size = rel(7)
62 | ) +
63 | theme_net() +
64 | labs(
65 | title = "Blood donation diagram",
66 | x = NULL,
67 | y = NULL,
68 | color = NULL,
69 | fill = NULL,
70 | caption = caption_text(
71 | source_text = cfg_day_17$source,
72 | day_type = cfg_day_17$category,
73 | day_hashtag = cfg_day_17$theme,
74 | day = cfg_day_17$day,
75 | color_text_1 = c3_color_text_2,
76 | color_text_2 = c3_color_text_1
77 | )
78 | ) +
79 | theme_my(
80 | font_regular = "redhat_regular",
81 | font_bold = "redhat_bold",
82 | font_light = "redhat_light",
83 | color_text_1 = c3_color_text_1,
84 | color_text_2 = c3_color_text_2,
85 | color_background = c3_color_background,
86 | title_size = 46
87 | ) +
88 | theme(panel.grid.major = element_blank(),
89 | axis.text = element_blank(),
90 | plot.caption = element_textbox_simple(
91 | size = 13,
92 | lineheight = .5,
93 | padding = margin(1, 1, 1, 1, "pt"),
94 | margin = margin(25, 0, 0, 0, "pt"),
95 | ))
96 |
97 |
98 |
99 | # Save --------------------------------------------------------------------
100 | ggsave(
101 | filename = "R/30DayChartChallenge2024/day_17/day_17_networks.png",
102 | plot = plot,
103 | width = 1080,
104 | height = 1296,
105 | units = "px",
106 | dpi = 320
107 | )
108 |
109 |
--------------------------------------------------------------------------------
/R/30DayChartChallenge2024/day_01/day_01_part_to_whole.R:
--------------------------------------------------------------------------------
1 | # 30DayChartChallenge2024 / day_01_part_to_whole
2 |
3 | # Libraries ---------------------------------------------------------------
4 | library(data.table)
5 | library(ggplot2)
6 | library(ggtext)
7 | library(emojifont)
8 | library(sysfonts)
9 | library(showtext)
10 |
11 |
12 | # Source ------------------------------------------------------------------
13 | source("R/30DayChartChallenge2024/theme/styles.R")
14 | source("R/30DayChartChallenge2024/theme/theme.R")
15 |
16 | # Config ------------------------------------------------------------------
17 | cfg <- yaml::read_yaml("R/30DayChartChallenge2024/cfg/plots.yml")[["default"]]
18 | cfg_day_1 <- cfg$day_1
19 |
20 | # Data --------------------------------------------------------------------
21 | data <- data.table(
22 | dependency = c("Number of crops", "Crop production"),
23 | value = c(.75, .35),
24 | comment = c(
25 | "Three-quarters of crops get a little help from their buzzing buddies",
26 | "75% of crops need a pollinator's help, but only ⅓ of our food actually depends on them!\nWhy? Cereals and other heavy hitters don't need the buzz."
27 | )
28 | )
29 |
30 | data[, dependency := factor(dependency, levels = c("Number of crops", "Crop production"))]
31 |
32 |
33 | # Plot --------------------------------------------------------------------
34 | plot <- data %>%
35 | ggplot(aes(value, dependency)) +
36 | geom_col(fill = color_set_1, just = 1) +
37 | facet_wrap( ~ dependency, ncol = 1, scales = "free_y") +
38 | geom_text(
39 | aes(label = paste0(" ", sprintf("%2.0f", 100 * value), "% "),
40 | hjust = 1.1, vjust = 3),
41 | color = color_background,
42 | size = rel(10),
43 | fontface = "bold",
44 | family = "inter_regular"
45 | ) +
46 | geom_text(
47 | aes(x = I(0), y = I(1.4), label = comment),
48 | color = color_text_1,
49 | size = rel(6),
50 | hjust = 0,
51 | family = "inter_light",
52 | lineheight = 0.4
53 | ) +
54 |
55 | scale_x_continuous(
56 | name = NULL,
57 | expand = c(0, 0),
58 | limits = c(0, 1),
59 | guide = "none"
60 | ) +
61 | scale_y_discrete(guide = "none") +
62 | scale_color_manual(values = c(color_text_1, color_background),
63 | guide = "none") +
64 | labs(title = "Without a Buzz, No Brussels Sprouts: How Pollinators Keep Our Plates Full",
65 | subtitle = "Percentage of Food We Owe to Busy Bees (and Their Buddies)",
66 | x = NULL,
67 | y = NULL,
68 | caption = caption_text(
69 | source_text = cfg_day_1$source,
70 | day_type = cfg_day_1$category,
71 | day_hashtag = cfg_day_1$theme,
72 | day = cfg_day_1$day
73 | )) +
74 |
75 | theme_my(title_size = 36) +
76 | theme(
77 | strip.background = element_rect(fill = color_background, color = color_background),
78 | strip.text = element_text(
79 | color = color_text_2,
80 | family = "inter_regular",
81 | hjust = 0,
82 | margin = margin(1, 1, 1, 1),
83 | face = "bold"
84 | ),
85 | panel.grid.major = element_blank(),
86 | panel.spacing = unit(1, "lines")
87 | )
88 |
89 |
90 | # Save --------------------------------------------------------------------
91 | ggsave(
92 | filename = "day_01_part_to_whole.png",
93 | path = normalizePath("R/30DayChartChallenge2024/day_01"),
94 | plot = plot,
95 | device = "png",
96 | units = "px",
97 | width = 1920,
98 | height = 1080,
99 | dpi = 320
100 | )
101 |
102 |
--------------------------------------------------------------------------------
/R/30DayChartChallenge2024/day_10/day_10_physical.R:
--------------------------------------------------------------------------------
1 | # 30DayChartChallenge2024 / day_10_physical
2 |
3 | # Libraries ---------------------------------------------------------------
4 | library(data.table)
5 | library(ggplot2)
6 | library(ggforce)
7 | library(ggtext)
8 | library(emojifont)
9 | library(sysfonts)
10 | library(showtext)
11 | library(patchwork)
12 |
13 |
14 | # Source ------------------------------------------------------------------
15 | source("R/30DayChartChallenge2024/theme/styles.R")
16 | source("R/30DayChartChallenge2024/theme/theme.R")
17 |
18 |
19 | # Config ------------------------------------------------------------------
20 | cfg <-
21 | yaml::read_yaml("R/30DayChartChallenge2024/cfg/plots.yml")[["default"]]
22 | cfg_day_10 <- cfg$day_10
23 |
24 |
25 | # Data --------------------------------------------------------------------
26 | dt <- fread("R/30DayChartChallenge2024/day_10/physical.csv")
27 | dt[, date := as.Date(date)]
28 |
29 | # Plot --------------------------------------------------------------------
30 | plot <- dt[, ggplot(.SD, aes(date, position)) +
31 | geom_hline(
32 | yintercept = 1,
33 | color = c2_color_text_2,
34 | linetype = "dashed",
35 | linewidth = 0.10
36 | ) +
37 | geom_line(color = c2_color_set_1, linewidth = 0.5) +
38 | geom_ribbon(aes(date, ymin = position, ymax = 100),
39 | fill = c2_color_set_1,
40 | alpha = .25) +
41 |
42 | scale_y_reverse(limits = c(100,-10),
43 | breaks = c(1, 5, seq(10, 100, 10))) +
44 | scale_x_date(breaks = .SD[seq(1, 26, 3), date], date_labels = "%d %b %y") +
45 | labs(
46 | title = "Physical by Olivia Newton-John",
47 | subtitle = "weeks on top of the Billboard Hot 100 chart in 1981/82",
48 | x = NULL,
49 | y = "position",
50 | caption = caption_text(
51 | source_text = cfg_day_10$source,
52 | day_type = cfg_day_10$category,
53 | day_hashtag = cfg_day_10$theme,
54 | day = cfg_day_10$day,
55 | color_text_1 = c2_color_text_1,
56 | color_text_2 = c2_color_text_2
57 | )
58 | ) +
59 | theme_my(
60 | font_regular = "roboto_regular",
61 | font_bold = "roboto_bold",
62 | font_light = "roboto_light",
63 | color_text_1 = c2_color_text_1,
64 | color_text_2 = c2_color_text_2,
65 | color_background = c2_color_background,
66 | title_size = 36
67 | ) +
68 | theme(
69 | plot.margin = margin(25, 10, 0, 15, "pt"),
70 | panel.grid.major = element_blank(),
71 | axis.text.y = element_text(
72 | size = 14,
73 | family = "roboto_bold",
74 | color = c2_color_text_2
75 | ),
76 | axis.text.x = element_text(
77 | size = 12,
78 | hjust = 0,
79 | family = "roboto_bold"
80 | )
81 | )]
82 |
83 | # Save --------------------------------------------------------------------
84 | ggsave(
85 | filename = "day_10_physical.png",
86 | path = normalizePath("R/30DayChartChallenge2024/day_10"),
87 | plot = plot,
88 | device = "png",
89 | units = "px",
90 | width = 1440,
91 | height = 1080,
92 | dpi = 320
93 | )
94 |
95 |
--------------------------------------------------------------------------------
/R/30DayChartChallenge2024/day_26/day_26_AI.R:
--------------------------------------------------------------------------------
1 | # 30DayChartChallenge2024 / day_26_AI
2 |
3 | # Libraries ---------------------------------------------------------------
4 | library(data.table)
5 | library(tidyverse)
6 | library(ggforce)
7 | library(ggtext)
8 | library(ggrepel)
9 | library(emojifont)
10 | library(sysfonts)
11 | library(showtext)
12 | library(ggplot2)
13 | library(tidyverse)
14 | library(mlmhelpr)
15 |
16 |
17 | # Source ------------------------------------------------------------------
18 | source("R/30DayChartChallenge2024/theme/styles.R")
19 | source("R/30DayChartChallenge2024/theme/theme.R")
20 |
21 |
22 | # Config ------------------------------------------------------------------
23 | cfg <-
24 | yaml::read_yaml("R/30DayChartChallenge2024/cfg/plots.yml")[["default"]]
25 | cfg_day_26 <- cfg$day_26
26 |
27 |
28 | # Data --------------------------------------------------------------------
29 | dt <- fread("R/30DayChartChallenge2024/day_26/ai.csv")
30 |
31 | dt <- melt(dt, id.vars = c("Type", "Group"))
32 |
33 |
34 |
35 | # Plot --------------------------------------------------------------------
36 |
37 |
38 | plot <- ggplot(data = dt, aes(x = Group, y = value, fill = variable)) +
39 |
40 | scale_fill_manual(values = c("#00f1bc", "#81d8d0", "#ea899a")) +
41 | labs(
42 | title = "Awareness of AI use in UK",
43 | subtitle = "Proportion of adults reporting how often they think\nthey can recognise when they are using AI\nGreat Britain, 26 July to 1 October 2023",
44 | x = NULL,
45 | y = "Proportion (%)",
46 | fill = "Frequency",
47 | caption = caption_text(
48 | source = cfg_day_26$source,
49 | day_type = cfg_day_26$category,
50 | day_hashtag = cfg_day_26$theme,
51 | day = cfg_day_26$day,
52 | color_text_1 = c2_color_text_1,
53 | color_text_2 = c2_color_text_2
54 | )
55 | ) +
56 |
57 | # Stacked bar chart
58 | geom_bar(stat = "identity", position = position_fill()) +
59 |
60 | # Display data labels within bars (optional)
61 | geom_text(
62 | aes(label = paste0(value, "%")),
63 | stat = "identity",
64 | position = position_fill(vjust = .5),
65 | vjust = 0.5,
66 | size = rel(7)
67 | ) +
68 |
69 | # Avoid overlapping x-axis labels if needed (consider rotating or wrapping)
70 | coord_flip() + # Flips x and y axes for better readability
71 | facet_grid(Type ~ ., scales = "free", space = "free") +
72 | scale_y_continuous(labels = scales::percent_format()) +
73 | guides(fill = guide_legend(nrow = 3, theme = theme(legend.byrow = TRUE))) +
74 | theme_my(
75 | font_regular = "roboto_regular",
76 | font_bold = "roboto_bold",
77 | font_light = "roboto_light",
78 | color_text_1 = c2_color_text_1,
79 | color_text_2 = c2_color_text_2,
80 | color_background = c2_color_background,
81 | title_size = 48
82 | ) +
83 | theme(
84 | legend.position = "bottom",
85 | axis.text = element_text(family = "roboto_regular",
86 | size = 26, hjust = 1),
87 | plot.margin = margin(25, 45, 25, 25, "pt"),
88 | plot.title.position = "plot",
89 | plot.caption.position = "plot",
90 | plot.caption = element_textbox_simple(
91 | size = 26,
92 | lineheight = .5,
93 | padding = margin(0, 0, 0, 0, "pt"),
94 | margin = margin(25, 0, 0, 0, "pt"),
95 | )
96 |
97 |
98 | )
99 |
100 |
101 | # Save --------------------------------------------------------------------
102 | ggsave(
103 | "R/30DayChartChallenge2024/day_26/day_26_AI.png",
104 | plot,
105 | width = 1920,
106 | height = 2560,
107 | units = "px",
108 | dpi = 320
109 | )
110 |
111 |
--------------------------------------------------------------------------------
/R/30DayChartChallenge2024/day_24/day_24_ILO_Africa.R:
--------------------------------------------------------------------------------
1 | # 30DayChartChallenge2024 / day_24_ILO_Africa
2 |
3 | # Libraries ---------------------------------------------------------------
4 | library(data.table)
5 | library(tidyverse)
6 | library(ggforce)
7 | library(ggtext)
8 | library(ggrepel)
9 | library(emojifont)
10 | library(sysfonts)
11 | library(showtext)
12 | library(patchwork)
13 | library(lubridate)
14 | library(zoo)
15 | library(terra)
16 | library(tidyterra)
17 | library(giscoR)
18 | library(sf)
19 | # devtools::install_github("mtennekes/tmaptools")
20 | library(tmaptools)
21 |
22 |
23 | # Source ------------------------------------------------------------------
24 | source("R/30DayChartChallenge2024/theme/styles.R")
25 | source("R/30DayChartChallenge2024/theme/theme.R")
26 |
27 |
28 | # Config ------------------------------------------------------------------
29 | cfg <-
30 | yaml::read_yaml("R/30DayChartChallenge2024/cfg/plots.yml")[["default"]]
31 | cfg_day_24 <- cfg$day_24
32 |
33 |
34 | # Data --------------------------------------------------------------------
35 | dt <- fread("R/30DayChartChallenge2024/day_24/ilo_poverty.csv")
36 | dt <- dt[!(ref_area.label %in% c("World", "Africa"))]
37 |
38 | # Plot --------------------------------------------------------------------
39 |
40 | plot <- dt[, ggplot(.SD, aes(time, obs_value / 100, color = ref_area.label )) +
41 | geom_line(linewidth = 1) +
42 | theme_my(
43 | font_regular = "josefin_regular",
44 | font_bold = "josefin_bold",
45 | font_light = "josefin_light",
46 | color_text_1 = c4_color_text_1,
47 | color_text_2 = c4_color_text_2,
48 | color_background = c4_color_background,
49 | title_size = 50
50 | ) +
51 | scale_color_manual(values = c4_col_set) +
52 | scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
53 | labs(
54 | title = "Working poverty rate in African Regions",
55 | subtitle = "% of employed adults and youth (15+) living below US$2.15 PPP",
56 | caption = caption_text(
57 | source_text = cfg_day_24$source,
58 | day_type = cfg_day_24$category,
59 | day_hashtag = cfg_day_24$theme,
60 | day = cfg_day_24$day,
61 | color_text_1 = c4_color_text_1,
62 | color_text_2 = c4_color_text_2
63 | ),
64 | x = NULL,
65 | y = "Working poverty rate (%)",
66 | color = NULL
67 | ) +
68 | theme(
69 | legend.position = "bottom",
70 | plot.margin = margin(25, 0, 15, 0, "pt"),
71 | plot.title = element_text(
72 | margin = margin(5, 5, 5, 0, "pt")
73 | ),
74 | plot.subtitle = element_text(
75 | margin = margin(5, 5, 5, 5, "pt")
76 | ),
77 | axis.text = element_text(
78 | size = rel(2),
79 | family = "josefin_bold",
80 | color = c4_color_text_2,
81 | margin = margin(2, 2, 2, 0, "pt")
82 | ),
83 | axis.title.y = element_text(
84 | size = 32,
85 | family = "josefin_bold",
86 | color = c4_color_text_2,
87 | margin = margin(5, 5, 5, 5, "pt"),
88 | angle = 90
89 | ),
90 | panel.grid.major = element_line(
91 | color = c4_color_text_2,
92 | linetype = "dotted",
93 | linewidth = .3,
94 | )
95 | )]
96 |
97 |
98 | # Save --------------------------------------------------------------------
99 | ggsave(
100 | filename = "R/30DayChartChallenge2024/day_24/day_24_ILO_Africa.png",
101 | plot = plot,
102 | width = 2688,
103 | height = 1920,
104 | units = "px",
105 | dpi = 320
106 | )
107 |
--------------------------------------------------------------------------------
/R/30DayChartChallenge2024/day_09/day_9_major_minor.R:
--------------------------------------------------------------------------------
1 | # 30DayChartChallenge2024 / day_9_major_minor
2 |
3 | # Libraries ---------------------------------------------------------------
4 | library(data.table)
5 | library(ggplot2)
6 | library(ggforce)
7 | library(ggtext)
8 | library(emojifont)
9 | library(sysfonts)
10 | library(showtext)
11 | library(patchwork)
12 |
13 |
14 | # Source ------------------------------------------------------------------
15 | source("R/30DayChartChallenge2024/theme/styles.R")
16 | source("R/30DayChartChallenge2024/theme/theme.R")
17 |
18 |
19 | # Config ------------------------------------------------------------------
20 | cfg <-
21 | yaml::read_yaml("R/30DayChartChallenge2024/cfg/plots.yml")[["default"]]
22 | cfg_day_9 <- cfg$day_9
23 |
24 |
25 | # Data --------------------------------------------------------------------
26 | dt <- fread("R/30DayChartChallenge2024/day_09/symphonies_by_key.csv")
27 | dt <- dt[, .N, .(note, key)] %>% dcast(note ~ key, value.var = "N")
28 |
29 | cols <- c("major", "minor")
30 | dt <- dt[, (cols) := lapply(.SD, nafill, fill = 0), .SDcols = cols]
31 | dt <- dt[order(major, minor, decreasing = TRUE)]
32 | dt <- melt(dt, id.vars = "note", variable.name = "key", value.name = "count")
33 | dt[, perc := round(count / sum(count) * 100, 1), by = note]
34 | dt <- dt[order(key, perc)]
35 | dt[, note := factor(note, levels = .SD[key == "major", note])]
36 | dt[, my_hjust := fifelse(key == "major", 1.1, -0.1)]
37 |
38 |
39 | # Plot --------------------------------------------------------------------
40 |
41 | plot <- dt[, ggplot(.SD, aes(
42 | x = note,
43 | y = fifelse(key == "major", perc, -perc),
44 | fill = key
45 | )) +
46 | geom_bar(stat = "identity") +
47 | geom_text(
48 | aes(
49 | label = paste0(" ", sprintf("%2.0f", perc), "% "),
50 | hjust = my_hjust
51 | ),
52 | color = c2_color_text_1,
53 | size = rel(5),
54 | family = "roboto_bold"
55 | ) +
56 | scale_fill_manual(breaks = c("minor", "major"),
57 | values = c("major" = "#13ae8c",
58 | "minor" = c2_color_accent_2),
59 | labels = c("Minor", "Major")) +
60 | labs(
61 | title = "Symphonies by Key",
62 | subtitle = "Major and Minor",
63 | x = NULL,
64 | y = NULL,
65 | fill = NULL,
66 | caption = caption_text(
67 | source_text = cfg_day_9$source,
68 | day_type = cfg_day_9$category,
69 | day_hashtag = cfg_day_9$theme,
70 | day = cfg_day_9$day,
71 | color_text_1 = c2_color_text_1,
72 | color_text_2 = c2_color_text_2
73 | )
74 | ) +
75 | coord_flip() +
76 | scale_y_continuous(guide = "none") +
77 | theme_my(
78 | font_regular = "roboto_regular",
79 | font_bold = "roboto_bold",
80 | font_light = "roboto_light",
81 | color_text_1 = c2_color_text_1,
82 | color_text_2 = c2_color_text_2,
83 | color_background = c2_color_background,
84 | title_size = 28
85 | ) +
86 | theme(
87 | plot.margin = margin(25, 10, 0, 15, "pt"),
88 | legend.position = "bottom",
89 | legend.margin = margin(0, 0, 0, 0, "pt"),
90 | legend.spacing = unit(5, "pt"),
91 | legend.key.spacing = unit(5, "pt"),
92 | legend.key.height = unit(6, 'pt'),
93 | legend.key.width = unit(9.708, 'pt'),
94 | axis.text.y = element_text(
95 | size = 12,
96 | family = "roboto_bold",
97 | color = c2_color_text_2
98 | )
99 | )]
100 |
101 | # Save --------------------------------------------------------------------
102 | ggsave(
103 | filename = "day_9_major_minor.png",
104 | path = normalizePath("R/30DayChartChallenge2024/day_09"),
105 | plot = plot,
106 | device = "png",
107 | units = "px",
108 | width = 1080,
109 | height = 1080,
110 | dpi = 320
111 | )
112 |
--------------------------------------------------------------------------------
/R/30DayChartChallenge2024/day_19/multiTimeline.csv:
--------------------------------------------------------------------------------
1 | Categoría: Todas las categorías
2 |
3 | Mes,dinosaurs: (Todo el mundo)
4 | 2005-01,56
5 | 2005-02,65
6 | 2005-03,64
7 | 2005-04,67
8 | 2005-05,61
9 | 2005-06,47
10 | 2005-07,42
11 | 2005-08,42
12 | 2005-09,48
13 | 2005-10,51
14 | 2005-11,57
15 | 2005-12,51
16 | 2006-01,60
17 | 2006-02,57
18 | 2006-03,56
19 | 2006-04,55
20 | 2006-05,55
21 | 2006-06,44
22 | 2006-07,41
23 | 2006-08,46
24 | 2006-09,36
25 | 2006-10,44
26 | 2006-11,48
27 | 2006-12,46
28 | 2007-01,49
29 | 2007-02,50
30 | 2007-03,47
31 | 2007-04,46
32 | 2007-05,50
33 | 2007-06,47
34 | 2007-07,49
35 | 2007-08,47
36 | 2007-09,48
37 | 2007-10,48
38 | 2007-11,51
39 | 2007-12,49
40 | 2008-01,54
41 | 2008-02,52
42 | 2008-03,57
43 | 2008-04,55
44 | 2008-05,52
45 | 2008-06,46
46 | 2008-07,46
47 | 2008-08,46
48 | 2008-09,62
49 | 2008-10,51
50 | 2008-11,54
51 | 2008-12,48
52 | 2009-01,48
53 | 2009-02,51
54 | 2009-03,60
55 | 2009-04,64
56 | 2009-05,66
57 | 2009-06,77
58 | 2009-07,87
59 | 2009-08,74
60 | 2009-09,62
61 | 2009-10,67
62 | 2009-11,63
63 | 2009-12,55
64 | 2010-01,59
65 | 2010-02,66
66 | 2010-03,68
67 | 2010-04,60
68 | 2010-05,59
69 | 2010-06,49
70 | 2010-07,54
71 | 2010-08,48
72 | 2010-09,50
73 | 2010-10,49
74 | 2010-11,54
75 | 2010-12,50
76 | 2011-01,49
77 | 2011-02,55
78 | 2011-03,55
79 | 2011-04,58
80 | 2011-05,57
81 | 2011-06,45
82 | 2011-07,45
83 | 2011-08,40
84 | 2011-09,53
85 | 2011-10,54
86 | 2011-11,54
87 | 2011-12,51
88 | 2012-01,59
89 | 2012-02,64
90 | 2012-03,57
91 | 2012-04,55
92 | 2012-05,58
93 | 2012-06,55
94 | 2012-07,55
95 | 2012-08,52
96 | 2012-09,70
97 | 2012-10,57
98 | 2012-11,57
99 | 2012-12,60
100 | 2013-01,57
101 | 2013-02,62
102 | 2013-03,65
103 | 2013-04,68
104 | 2013-05,62
105 | 2013-06,55
106 | 2013-07,60
107 | 2013-08,55
108 | 2013-09,52
109 | 2013-10,54
110 | 2013-11,62
111 | 2013-12,84
112 | 2014-01,81
113 | 2014-02,67
114 | 2014-03,71
115 | 2014-04,66
116 | 2014-05,64
117 | 2014-06,54
118 | 2014-07,59
119 | 2014-08,54
120 | 2014-09,55
121 | 2014-10,51
122 | 2014-11,57
123 | 2014-12,52
124 | 2015-01,56
125 | 2015-02,56
126 | 2015-03,58
127 | 2015-04,58
128 | 2015-05,63
129 | 2015-06,100
130 | 2015-07,71
131 | 2015-08,60
132 | 2015-09,58
133 | 2015-10,58
134 | 2015-11,62
135 | 2015-12,63
136 | 2016-01,63
137 | 2016-02,61
138 | 2016-03,58
139 | 2016-04,60
140 | 2016-05,61
141 | 2016-06,51
142 | 2016-07,54
143 | 2016-08,48
144 | 2016-09,49
145 | 2016-10,49
146 | 2016-11,48
147 | 2016-12,52
148 | 2017-01,56
149 | 2017-02,57
150 | 2017-03,59
151 | 2017-04,56
152 | 2017-05,53
153 | 2017-06,49
154 | 2017-07,49
155 | 2017-08,47
156 | 2017-09,49
157 | 2017-10,47
158 | 2017-11,48
159 | 2017-12,52
160 | 2018-01,51
161 | 2018-02,54
162 | 2018-03,54
163 | 2018-04,53
164 | 2018-05,55
165 | 2018-06,71
166 | 2018-07,79
167 | 2018-08,67
168 | 2018-09,56
169 | 2018-10,54
170 | 2018-11,55
171 | 2018-12,50
172 | 2019-01,49
173 | 2019-02,50
174 | 2019-03,55
175 | 2019-04,56
176 | 2019-05,48
177 | 2019-06,45
178 | 2019-07,44
179 | 2019-08,43
180 | 2019-09,43
181 | 2019-10,42
182 | 2019-11,41
183 | 2019-12,43
184 | 2020-01,44
185 | 2020-02,45
186 | 2020-03,43
187 | 2020-04,48
188 | 2020-05,47
189 | 2020-06,48
190 | 2020-07,47
191 | 2020-08,48
192 | 2020-09,48
193 | 2020-10,46
194 | 2020-11,43
195 | 2020-12,46
196 | 2021-01,50
197 | 2021-02,52
198 | 2021-03,45
199 | 2021-04,47
200 | 2021-05,46
201 | 2021-06,47
202 | 2021-07,43
203 | 2021-08,43
204 | 2021-09,42
205 | 2021-10,39
206 | 2021-11,40
207 | 2021-12,47
208 | 2022-01,46
209 | 2022-02,46
210 | 2022-03,45
211 | 2022-04,51
212 | 2022-05,52
213 | 2022-06,57
214 | 2022-07,51
215 | 2022-08,46
216 | 2022-09,45
217 | 2022-10,41
218 | 2022-11,39
219 | 2022-12,40
220 | 2023-01,44
221 | 2023-02,49
222 | 2023-03,48
223 | 2023-04,45
224 | 2023-05,41
225 | 2023-06,41
226 | 2023-07,44
227 | 2023-08,43
228 | 2023-09,42
229 | 2023-10,43
230 | 2023-11,44
231 | 2023-12,41
232 | 2024-01,43
233 | 2024-02,45
234 | 2024-03,42
235 | 2024-04,41
236 |
--------------------------------------------------------------------------------
/R/30DayChartChallenge2024/theme/styles.R:
--------------------------------------------------------------------------------
1 | # libs -----------------------------------------------------------------------
2 | library(sysfonts)
3 | library(showtext)
4 | library(ggplot2)
5 |
6 |
7 | # Colors ------------------------------------------------------------------
8 | color_background <- "#fbfdfe"
9 | color_text_1 <- "#352725"
10 | color_text_2 <- "#3f68e3"
11 | color_set_1 <- "#2a668a"
12 | color_set_2 <- "#f9ad0d"
13 | color_set_3 <- "#67deb0"
14 |
15 |
16 | c2_color_background <- "#0e0204"
17 | c2_color_text_1 <- "#f1f2f4"
18 | c2_color_text_2 <- "#d2f796"
19 | c2_color_accent_1 <- "#00f1bc"
20 | c2_color_accent_2 <- "#fe686c"
21 | c2_color_set_1 <- "#992696"
22 | c2_color_set_2 <- "#ba3339"
23 | c2_color_set_3 <- "#636567"
24 |
25 |
26 |
27 | c3_color_background <- "#1A7070"
28 | c3_color_text_1 <- "#FFE44D"
29 | c3_color_text_2 <- "#DEEDF9"
30 | c3_color_accent_1 <- "#d6762c"
31 | c3_color_accent_2 <- "#451a70"
32 | c3_color_set_1 <- "#869b97"
33 | c3_color_set_2 <- "#ff9a9b"
34 | c3_color_set_3 <- "#44bcc6"
35 |
36 |
37 |
38 | c4_color_background <- "#cddfe0"
39 | c4_color_text_1 <- "#0e130b"
40 | c4_color_text_2 <- "#103c43"
41 |
42 |
43 | c4_color_set_1 <- "#db4726"
44 | c4_color_set_2 <- "#4170ab"
45 | c4_color_set_3 <- "#f4c14c"
46 | c4_color_set_4 <- "#e7c2ba"
47 |
48 | c4_col_set <- c(
49 | "#387c2b", "#fa6400",
50 | "#ffa100", "#949494",
51 | "#0099c4", "#6e3ab7"
52 | )
53 |
54 |
55 | c4_color_accent_1 <- "#18984b"
56 | c4_color_accent_2 <- "#e6c51b"
57 | c4_color_accent_3 <- "#ed0c29"
58 |
59 |
60 |
61 |
62 | # ** pallettes ------------------------------------------------------------
63 | gradient <-
64 | c(color_set_1,
65 | "#0089a4",
66 | "#00aba9",
67 | "#40cb9b",
68 | "#9ce582",
69 | "#f9f871")
70 |
71 | main <-
72 | c(color_set_1,
73 | "#6399c0",
74 | color_set_2,
75 | "#b6ab00",
76 | color_set_3,
77 | "#384b42")
78 |
79 |
80 |
81 | # ** aux colors -----------------------------------------------------------
82 | white <- "#F0F0F0"
83 | light_gray <- "#fcfcfd"
84 | medium_gray <- "#d2d2d2"
85 | dark_gray <- "#3c3c3c"
86 |
87 |
88 |
89 | # Fonts -------------------------------------------------------------------
90 | font_add_google(name = "Inter", family = "inter_regular", regular.wt = 400, bold.wt = 700)
91 | font_add_google(name = "Inter", family = "inter_bold", regular.wt = 700, bold.wt = 900)
92 | font_add_google(name = "Inter", family = "inter_light", regular.wt = 300, bold.wt = 400)
93 | font_add_google(name = "Inter", family = "inter_thin", regular.wt = 100, bold.wt = 200)
94 |
95 | # Roboto
96 | font_add_google(name = "Roboto", family = "roboto_regular", regular.wt = 400, bold.wt = 700)
97 | font_add_google(name = "Roboto", family = "roboto_bold", regular.wt = 700, bold.wt = 900)
98 | font_add_google(name = "Roboto", family = "roboto_light", regular.wt = 300, bold.wt = 400)
99 | font_add_google(name = "Roboto", family = "roboto_thin", regular.wt = 100, bold.wt = 200)
100 |
101 | # Red Hat Mono
102 | font_add_google(name = "Red Hat Mono", family = "redhat_regular", regular.wt = 500, bold.wt = 600)
103 | font_add_google(name = "Red Hat Mono", family = "redhat_bold", regular.wt = 700, bold.wt = 900)
104 | font_add_google(name = "Red Hat Mono", family = "redhat_light", regular.wt = 400, bold.wt = 500)
105 |
106 | # Josefin Sans
107 | font_add_google(name = "Josefin Sans", family = "josefin_regular", regular.wt = 400, bold.wt = 700)
108 | font_add_google(name = "Josefin Sans", family = "josefin_bold", regular.wt = 700, bold.wt = 900)
109 | font_add_google(name = "Josefin Sans", family = "josefin_light", regular.wt = 300, bold.wt = 400)
110 | font_add_google(name = "Josefin Sans", family = "josefin_thin", regular.wt = 100, bold.wt = 200)
111 |
112 |
113 |
114 |
115 | # Font Awesome
116 | font_add(family = "fa-brands", regular = "R/30DayChartChallenge2024/theme/fa-brands-400.ttf")
117 | font_add(family = "fa-solid", regular = "R/30DayChartChallenge2024/theme/fa-solid-900.ttf")
118 | showtext_auto()
119 |
120 |
--------------------------------------------------------------------------------
/R/30DayChartChallenge2024/day_14/day_14_heatmap.R:
--------------------------------------------------------------------------------
1 | # 30DayChartChallenge2024 / day_14_heatmap
2 |
3 | # Libraries ---------------------------------------------------------------
4 | library(data.table)
5 | library(tidyverse)
6 | library(ggforce)
7 | library(ggtext)
8 | library(ggrepel)
9 | library(emojifont)
10 | library(sysfonts)
11 | library(showtext)
12 | library(patchwork)
13 | library(lubridate)
14 |
15 |
16 | # Source ------------------------------------------------------------------
17 | source("R/30DayChartChallenge2024/theme/styles.R")
18 | source("R/30DayChartChallenge2024/theme/theme.R")
19 |
20 |
21 | # Config ------------------------------------------------------------------
22 | cfg <-
23 | yaml::read_yaml("R/30DayChartChallenge2024/cfg/plots.yml")[["default"]]
24 | cfg_day_14 <- cfg$day_14
25 |
26 |
27 | # Data --------------------------------------------------------------------
28 | dt <- fread("R/30DayChartChallenge2024/day_14/no2_calendar_data.csv", encoding = "Latin-1")
29 |
30 | # Update to english
31 | Sys.setlocale("LC_TIME", "English")
32 |
33 | dt[, wday := factor(wday(fecha, label = TRUE),
34 | levels = c("Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"))]
35 | dt[, month := factor(
36 | month(fecha, label = TRUE),
37 | levels = c(
38 | "Jan",
39 | "Feb",
40 | "Mar",
41 | "Apr",
42 | "May",
43 | "Jun",
44 | "Jul",
45 | "Aug",
46 | "Sep",
47 | "Oct",
48 | "Nov",
49 | "Dec"
50 | )
51 | )]
52 |
53 |
54 | # Plot --------------------------------------------------------------------
55 |
56 | plot <- dt[,
57 | ggplot(.SD, aes(
58 | x = wmonth,
59 | y = reorder(wday, -as.numeric(wday)),
60 | fill = valor_promedio
61 | )) +
62 | geom_tile(colour = "white") +
63 | facet_grid(year ~ month) +
64 | scale_x_continuous(breaks = 1:5, limits = c(0, 6)) +
65 | scale_fill_gradient(low = "#fedbd2", high = "#C20000", ) +
66 | labs(
67 | x = "Week of the month",
68 | y = NULL,
69 | title = "Nitrogen dioxide concentration in the city of Madrid",
70 | subtitle = "Average concentration of NO2 in the air by day of the week",
71 | fill = paste(unique(nom_abv), unique(ud_med)),
72 | caption = caption_text(
73 | source_text = cfg_day_14$source,
74 | day_type = cfg_day_14$category,
75 | day_hashtag = cfg_day_14$theme,
76 | day = cfg_day_14$day,
77 | color_text_1 = c2_color_text_1,
78 | color_text_2 = c2_color_text_2
79 | )
80 | ) +
81 | theme_my(
82 | font_regular = "redhat_regular",
83 | font_bold = "redhat_bold",
84 | font_light = "redhat_light",
85 | color_text_1 = c3_color_text_1,
86 | color_text_2 = c3_color_text_2,
87 | color_background = c3_color_background,
88 | title_size = 56
89 | ) +
90 | theme(
91 | plot.margin = margin(15, 15, 5, 15, "pt"),
92 | plot.caption = element_textbox_simple(
93 | size = 26,
94 | lineheight = .5,
95 | padding = margin(5, 5, 5, 5, "pt"),
96 | margin = margin(10, 0, 0, 0, "pt"),
97 | ),
98 | legend.position = "bottom",
99 | legend.spacing = unit(5, "pt"),
100 | legend.key.spacing = unit(5, "pt"),
101 | legend.key.height= unit(10, 'pt'),
102 | legend.key.width = unit(16.18, 'pt'),
103 | panel.grid.major = element_line(
104 | colour = c3_color_text_2,
105 | linetype = "solid",
106 | linewidth = .3
107 | ),
108 | axis.text = element_text(
109 | size = rel(1.6),
110 | family = "redhat_regular",
111 | color = c3_color_text_2,
112 | margin = margin(2, 2, 2, 0, "pt")
113 | )
114 | )
115 |
116 | ]
117 |
118 |
119 | # Save --------------------------------------------------------------------
120 | ggsave(
121 | filename = "R/30DayChartChallenge2024/day_14/day_14_heatmap.png",
122 | plot = plot,
123 | width = 2560,
124 | height = 2560,
125 | units = "px",
126 | dpi = 320)
127 |
128 |
129 |
130 |
--------------------------------------------------------------------------------
/R/30DayChartChallenge2024/day_05/day_5_diverging.R:
--------------------------------------------------------------------------------
1 | # 30DayChartChallenge2024 / day_5_diverging
2 |
3 | # Libraries ---------------------------------------------------------------
4 | library(data.table)
5 | library(ggplot2)
6 | library(ggstats)
7 | library(ggtext)
8 | library(sysfonts)
9 | library(showtext)
10 |
11 | # Source ------------------------------------------------------------------
12 | source("R/30DayChartChallenge2024/theme/styles.R")
13 | source("R/30DayChartChallenge2024/theme/theme.R")
14 |
15 |
16 | # Config ------------------------------------------------------------------
17 | cfg <-
18 | yaml::read_yaml("R/30DayChartChallenge2024/cfg/plots.yml")[["default"]]
19 | cfg_day_5 <- cfg$day_5
20 |
21 |
22 | # Data --------------------------------------------------------------------
23 | dt <- fread("R/30DayChartChallenge2024/day_05/ideo.csv")
24 | dt[, position := fcase(
25 | position %in% c("1 Izquierda", "2"),
26 | "Left",
27 | position %in% c("3", "4"),
28 | "Center-Left",
29 | position %in% c("5", "6"),
30 | "Center",
31 | position %in% c("7", "8"),
32 | "Center-Right",
33 | position %in% c("9", "10 Derecha"),
34 | "Right"
35 | )]
36 | dt[, position := factor(position,
37 | levels = c("Right", "Center-Right", "Center", "Center-Left", "Left"))]
38 |
39 | dt[, age := factor(age,
40 | levels = c("18-24", "25-34", "35-44", "45-54", "55-64", "65-74", "75+"))]
41 |
42 | dt_mw <-
43 | melt(dt[, .(age, position, m, w)], id.vars = c("position", "age"))
44 | dt_mw <-
45 | dt_mw[, .(value = sum(value)), by = .(position, age, variable)]
46 | dt_mw[, pct := value / sum(value), by = .(age, variable)]
47 | dt_mw[, variable := factor(variable,
48 | labels = c("Men", "Women"),
49 | levels = c("m", "w"))]
50 |
51 |
52 | # Plot --------------------------------------------------------------------
53 | custom_label <- function(x) {
54 | p <- scales::percent(x, accuracy = 1)
55 | p[x < .075] <- ""
56 | p
57 | }
58 |
59 | colors <- c("#d93328", "#f05d5d", "#999999", "#5da7f0", "#3366cc")
60 |
61 | plot <-
62 | dt_mw[, ggplot(.SD, aes(variable, pct, fill = reorder(position,-as.numeric(position)))) +
63 | geom_bar(stat = "identity", position = "likert") +
64 | geom_text(
65 | aes(
66 | label = paste0(" ", sprintf("%2.0f", 100 * pct), "% "),
67 | hjust = fifelse(position == "Right", .65, 0.5),
68 | ),
69 | color = color_background,
70 | size = rel(5),
71 | family = "inter_regular",
72 | position = position_likert(vjust = 0.5)
73 | ) +
74 | scale_fill_manual(values = colors) +
75 | facet_wrap( ~ age, scales = "fixed", ncol = 1) +
76 | coord_flip() +
77 | scale_y_continuous(limits = c(-.70, .70), guide = "none") +
78 | labs(
79 | title = "Ideological self-positioning in Spain (2023)",
80 | subtitle = "Percentage by age group and sex",
81 | x = NULL,
82 | y = NULL,
83 | fill = NULL,
84 | caption = caption_text(
85 | source_text = cfg_day_5$source,
86 | day_type = cfg_day_5$category,
87 | day_hashtag = cfg_day_5$theme,
88 | day = cfg_day_5$day
89 | )
90 | ) +
91 | theme_my() +
92 | theme(
93 | legend.position = "bottom",
94 | legend.spacing = unit(5, "pt"),
95 | legend.key.spacing = unit(5, "pt"),
96 | legend.key.height = unit(6, 'pt'),
97 | legend.key.width = unit(9.708, 'pt'),
98 | panel.grid.major = element_blank(),
99 | plot.margin = margin(25, 15, 15, 20, "pt")
100 | )]
101 |
102 |
103 | # Save --------------------------------------------------------------------
104 | ggsave(
105 | filename = "day_5_diverging.png",
106 | path = normalizePath("R/30DayChartChallenge2024/day_05"),
107 | plot = plot,
108 | device = "png",
109 | units = "px",
110 | width = 1080,
111 | height = 1747.44,
112 | dpi = 320
113 | )
114 |
--------------------------------------------------------------------------------
/R/30DayChartChallenge2024/cfg/plots.yml:
--------------------------------------------------------------------------------
1 | default:
2 | day_1:
3 | day: 1
4 | theme: part-to-whole
5 | category: Comparisons
6 | source: [Marcelo Aizen et al. (2019) and Alexandra-Maria Klein et al. (2006). | WorldinData.org]
7 | day_2:
8 | day: 2
9 | theme: neo
10 | category: Comparisons
11 | source: [Markandya & Wilkinson (2007); Sovacool et al. (2016); UNSCEAR (2008; & 2018) | OurWorldInData.org/energy]
12 | day_3:
13 | day: 3
14 | theme: makeover
15 | link: https://www.kff.org/other/issue-brief/data-note-public-awareness-antibiotic-resistance/
16 | figure: Figure 8- Most Of The Public Unaware Antibiotic Resistance Is Unrelated To The Outbreak Of Viruses Such As Measles
17 | category: Comparisons
18 | source: KFF Health Tracking Poll (conducted May 30-June 4, 2019)
19 | day_4:
20 | day: 4
21 | theme: waffle
22 | category: Comparisons
23 | source: Portal de datos abiertos del Ayuntamiento de Madrid
24 | day_5:
25 | day: 5
26 | theme: diverging
27 | category: Comparisons
28 | source: Spanish Sociological Research Center (CIS)
29 | day_6:
30 | day: 6
31 | theme: data day OECD
32 | category: Comparisons
33 | source: OECD
34 | day_7:
35 | day: 7
36 | theme: hazards
37 | category: Distributions
38 | source: Ministerio de Agricultura y Pesca, Alimentación y Medio Ambiente
39 | day_8:
40 | day: 8
41 | theme: circular
42 | category: Distributions
43 | source: Portal de datos abiertos del Ayuntamiento de Madrid
44 | day_9:
45 | day: 9
46 | theme: major/minor
47 | category: Distributions
48 | source: Wikipedia
49 | day_10:
50 | day: 10
51 | theme: physical
52 | category: Distributions
53 | source: Billboard Database
54 | day_11:
55 | day: 11
56 | theme: mobile-friendly
57 | category: Distributions
58 | source: Prepared by the author, based on The Collatz Conjecture
59 | day_12:
60 | day: 12
61 | theme: theme day- Reuters Graphics
62 | category: Distributions
63 | source: Economist Intelligence Unit (2023)
64 | day_13:
65 | day: 13
66 | theme: family
67 | category: Relationships
68 | source: Matthews Data
69 | day_14:
70 | day: 14
71 | theme: heatmap
72 | category: Relationships
73 | source: Red de Vigilancia de la Calidad del Aire del Ayto. de Madrid
74 | day_15:
75 | day: 15
76 | theme: historical
77 | category: Relationships
78 | source: U.S. Bureau of Labor Statistics
79 | day_16:
80 | day: 16
81 | theme: weather
82 | category: Relationships
83 | source: Spanish Meteorological Agency (AEMET)
84 | day_17:
85 | day: 17
86 | theme: networks
87 | category: Relationships
88 | source: "{ggnetwork}: blood"
89 | day_18:
90 | day: 18
91 | theme: DataDay
92 | category: Relationships
93 | source: Asian Development Bank
94 | day_19:
95 | day: 19
96 | theme: dinosaurs
97 | category: Timeseries
98 | source: Google Trends
99 | day_20:
100 | day: 20
101 | theme: correlation
102 | category: Timeseries
103 | source: INE | Insee
104 | day_21:
105 | day: 21
106 | theme: GreenEnergy
107 | category: Timeseries
108 | source: Eurostat
109 | day_22:
110 | day: 22
111 | theme: mobility
112 | category: Timeseries
113 | source: Eurostat
114 | day_23:
115 | day: 23
116 | theme: tiles
117 | category: Timeseries
118 | source: GHSL Data Package 2023
119 | day_24:
120 | day: 24
121 | theme: DataDay
122 | category: Timeseries
123 | source: ILO Africa
124 | day_25:
125 | day: 25
126 | theme: GlobalChange
127 | category: Uncertainties
128 | source: NSIDC
129 | day_26:
130 | day: 26
131 | theme: AI
132 | category: Uncertainties
133 | source: UK ONS
134 | day_27:
135 | day: 27
136 | theme: GoodBad
137 | category: Uncertainties
138 | source: FUNCAS
139 | day_28:
140 | day: 28
141 | theme: trend
142 | category: Uncertainties
143 | source: Instituto Canario de Estadística
144 | day_29:
145 | day: 29
146 | theme: black_n_white
147 | category: Uncertainties
148 | source: Prepared by the author
149 | day_30:
150 | day: 30
151 | theme: FiveThirtyEight
152 | category: Uncertainties
153 | source: FiveThirtyEight
154 |
--------------------------------------------------------------------------------
/R/30DayChartChallenge2024/day_02/day_02_neo.R:
--------------------------------------------------------------------------------
1 | # 30DayChartChallenge2024 / day_02_neo
2 |
3 | # Libraries ---------------------------------------------------------------
4 | library(data.table)
5 | library(ggplot2)
6 | library(ggforce)
7 | library(ggtext)
8 | library(emojifont)
9 | library(sysfonts)
10 | library(showtext)
11 |
12 |
13 | # Source ------------------------------------------------------------------
14 | source("R/30DayChartChallenge2024/theme/styles.R")
15 | source("R/30DayChartChallenge2024/theme/theme.R")
16 |
17 | # Config ------------------------------------------------------------------
18 | cfg <- yaml::read_yaml("R/30DayChartChallenge2024/cfg/plots.yml")[["default"]]
19 | cfg_day_2 <- cfg$day_2
20 |
21 |
22 | # Data --------------------------------------------------------------------
23 | death_rates_energy <- fread("R/30DayChartChallenge2024/day_02/death-rates-from-energy-production-per-twh.csv")
24 | death_rates_energy[, label := paste0(Entity, ": ", `Deaths per TWh of electricity production`)]
25 | label_length <- death_rates_energy[, max(nchar(as.character(label)))] + 2
26 | death_rates_energy[, label := paste0(label, strrep(" ", label_length - nchar(as.character(label))))]
27 | death_rates_energy[, Entity := factor(Entity, levels = Entity[order(`Deaths per TWh of electricity production`)])]
28 | death_rates_energy <- death_rates_energy[order(Entity)]
29 |
30 |
31 | # Don't know why but necessary
32 | death_rates_energy[, label := fcase(
33 | Entity == "Solar", paste0(" ", label),
34 | Entity == "Wind", paste0(" ", label),
35 | Entity == "Nuclear", paste0(" ", label),
36 | Entity == "Hydropower", paste0(" ", label),
37 | Entity == "Gas", paste0(" ", label),
38 | Entity == "Biomass", paste0(" ", label),
39 | Entity == "Oil", paste0(" ", label),
40 | Entity == "Coal", paste0(" ", label),
41 | Entity == "Brown coal", label
42 | )]
43 |
44 |
45 |
46 | # Plot --------------------------------------------------------------------
47 | plot <- ggplot(
48 | death_rates_energy,
49 | aes(
50 | x = Entity,
51 | xend = Entity,
52 | y = 0,
53 | yend = `Deaths per TWh of electricity production`
54 | )
55 | ) +
56 | geom_text(
57 | aes(label = label),
58 | hjust = -.2,
59 | family = "inter_bold",
60 | color = color_text_1,
61 | size = rel(5),
62 | ) +
63 | geom_link(size = 3.5,
64 | lineend = "round",
65 | color = color_set_2) +
66 | geom_link(size = 2.2,
67 | lineend = "round",
68 | color = color_set_1) +
69 | scale_y_continuous(limits = c(0, 40)) +
70 | coord_radial(theta = "y",
71 | -1.09 * pi,
72 | end = 0.9 * pi,
73 | inner.radius = .15) +
74 | geom_richtext(aes(I(.12), I(0), label = ""),
75 | size = 24,
76 | label.colour = NA,
77 | fill = NA,
78 | col = color_set_2,
79 | inherit.aes = F) +
80 | geom_richtext(aes(I(0), I(0), label = ""),
81 | size = 20,
82 | label.colour = NA,
83 | fill = NA,
84 | col = color_set_1,
85 | inherit.aes = F) +
86 | labs(
87 | title = "Death rates per unit of electricity production",
88 | subtitle = "Death rates are measured based on deaths from\naccidents and air pollution per terawatt-hour of electricity",
89 | caption = caption_text(
90 | source_text = cfg_day_2$source,
91 | day_type = cfg_day_2$category,
92 | day_hashtag = cfg_day_2$theme,
93 | day = cfg_day_2$day
94 | ),
95 | x = NULL,
96 | y = NULL
97 | ) +
98 | theme_my(title_size = 24) +
99 | theme(
100 | panel.grid.major = element_blank(),
101 | plot.margin = margin(1, 0, 0, 0, "cm"),
102 | axis.text = element_blank(),
103 | plot.subtitle = element_text(lineheight = .25, vjust = 1),
104 | plot.caption = element_textbox_simple(
105 | lineheight = .5,
106 | padding = margin(.1, .1, .1, .1, "lines"),
107 | margin = margin(0, 0, 1, 0, "lines"),
108 | )
109 | )
110 |
111 | # Save --------------------------------------------------------------------
112 | ggsave(
113 | filename = "day_02_neo.png",
114 | path = normalizePath("R/30DayChartChallenge2024/day_02"),
115 | plot = plot,
116 | device = "png",
117 | units = "px",
118 | width = 1080,
119 | height = 1080,
120 | dpi = 320
121 | )
122 |
123 |
124 |
125 |
126 |
127 |
128 |
--------------------------------------------------------------------------------
/R/30DayChartChallenge2024/day_08/day_8_circular.R:
--------------------------------------------------------------------------------
1 | # 30DayChartChallenge2024 / day_8_circular
2 |
3 | # Libraries ---------------------------------------------------------------
4 | library(data.table)
5 | library(ggplot2)
6 | library(ggforce)
7 | library(ggtext)
8 | library(emojifont)
9 | library(sysfonts)
10 | library(showtext)
11 | library(patchwork)
12 |
13 |
14 | # Source ------------------------------------------------------------------
15 | source("R/30DayChartChallenge2024/theme/styles.R")
16 | source("R/30DayChartChallenge2024/theme/theme.R")
17 |
18 |
19 | # Config ------------------------------------------------------------------
20 | cfg <-
21 | yaml::read_yaml("R/30DayChartChallenge2024/cfg/plots.yml")[["default"]]
22 | cfg_day_8 <- cfg$day_8
23 |
24 |
25 | # Data ----------------------------------------------------------------
26 | dt <-
27 | readRDS("R/30DayChartChallenge2024/day_08/pm10_mean_zona_2001.RDS")
28 |
29 | dt[, rolling_mean_10y := frollmean(mean_zona, 10, align = "right", fill = NA), zona]
30 | dt[, rolling_sd_10y := frollapply(mean_zona, 10, sd, align = "right", fill = NA), zona]
31 | dt[, yday := yday(fecha)]
32 | dt[, ymin := rolling_mean_10y - 2 * rolling_sd_10y]
33 | dt[, ymax := rolling_mean_10y + 2 * rolling_sd_10y]
34 |
35 |
36 | plot <- dt[fecha >= "2023-01-01" &
37 | zona == "Interior M30", ggplot(.SD, aes(yday, mean_zona)) +
38 | geom_ribbon(data = .SD[fecha <= "2023-12-31"],
39 | aes(ymin = ymin,
40 | ymax = ymax,
41 | fill = "± 2sd"),
42 | alpha = 0.33) +
43 | geom_line(data = .SD[fecha <= "2023-12-31"], aes(color = "PM10 concentration")) +
44 | geom_line(data = .SD[fecha <= "2023-12-31"],
45 | aes(y = rolling_mean_10y, color = "10y roll mean")) +
46 | scale_y_continuous(labels = scales::number_format(accuracy = 1)) +
47 | scale_color_manual(values = c("PM10 concentration" = c2_color_text_2,
48 | "10y roll mean" = c2_color_accent_2)) +
49 | scale_fill_manual(values = c("± 2sd" = c2_color_accent_1)) +
50 | labs(
51 | title = "Daily air quality in Madrid in 2023",
52 | subtitle = "PM10 mean concentration Interior M30 (Central Madrid)",
53 | x = NULL,
54 | y = "PM10 concentration (µg/m³)",
55 | fill = NULL,
56 | color = NULL,
57 | caption = caption_text(
58 | source_text = cfg_day_8$source,
59 | day_type = cfg_day_8$category,
60 | day_hashtag = cfg_day_8$theme,
61 | day = cfg_day_8$day,
62 | color_text_1 = c2_color_text_1,
63 | color_text_2 = c2_color_text_2
64 | )
65 | ) +
66 | coord_radial(
67 | inner.radius = .25,
68 | rotate_angle = TRUE,
69 | expand = FALSE,
70 | r_axis_inside = FALSE,
71 | direction = 1
72 | ) +
73 | scale_x_continuous(breaks = cumsum(c(31, 28, 31, 30 , 31 , 31, 30, 31, 30, 31, 30, 31))) +
74 | theme_my(
75 | font_regular = "roboto_regular",
76 | font_bold = "roboto_bold",
77 | font_light = "roboto_light",
78 | color_text_1 = c2_color_text_1,
79 | color_text_2 = c2_color_text_2,
80 | color_background = c2_color_background,
81 | title_size = 24
82 | ) +
83 | theme(plot.margin = margin(25, 5, 5, 0, "pt"),
84 | legend.position = "bottom",
85 | legend.margin = margin(0, 0, 0, 0, "pt"),
86 | legend.spacing = unit(5, "pt"),
87 | legend.key.spacing = unit(5, "pt"),
88 | legend.key.height = unit(6, 'pt'),
89 | legend.key.width = unit(9.708, 'pt'),
90 | axis.title.y = element_text(
91 | hjust = 0.5,
92 | vjust = 5
93 | ))]
94 |
95 | # Save --------------------------------------------------------------------
96 | ggsave(
97 | filename = "day_8_circular.png",
98 | path = normalizePath("R/30DayChartChallenge2024/day_08"),
99 | plot = plot,
100 | device = "png",
101 | units = "px",
102 | width = 1080,
103 | height = 1080,
104 | dpi = 320
105 | )
106 |
--------------------------------------------------------------------------------
/R/2024/week_02/2024_w02_lego_map.R:
--------------------------------------------------------------------------------
1 | # Header ------------------------------------------------------------------
2 | #
3 | # Author: Michal Kinel
4 | # Copyright (c) Michal Kinel, 2024
5 | # Email: michal.kinel@gmail.com
6 | #
7 | # Date: 2024-01-14
8 | #
9 | # Script Name: 2024_w02_lego_map.R
10 | #
11 | # Script Description: Make lego style map of Poland of the % eco farms
12 | #
13 | #
14 | # Notes:
15 | #
16 | #
17 |
18 | # Set options -------------------------------------------------------------
19 | cat("Setting options... \n\n", sep = "")
20 | options(scipen = 999) # turns off scientific notation
21 | options(encoding = "UTF-8") # sets string encoding to UTF-8 instead of ANSI
22 |
23 |
24 | # Install packages & load libraries ---------------------------------------
25 | cat("Install packages & load libraries... \n\n", sep = "")
26 | packages <- c("tidyverse", "data.table", "sf", "raster", "extrafont") # list of packages to load
27 | n_packages <- length(packages) # count how many packages are required
28 |
29 | new_pkg <- packages[!(packages %in% installed.packages())] # determine which packages aren't installed
30 |
31 | # Install missing packages
32 | if(length(new_pkg)){
33 | install.packages(new_pkg)
34 | }
35 |
36 | # Load all requried libraries
37 | for(n in 1:n_packages){
38 | cat("Loading Library #", n, " of ", n_packages, "... Currently Loading: ", packages[n], "\n", sep = "")
39 | lib_load <- paste("library(\"",packages[n],"\")", sep = "") # create string of text for loading each library
40 | eval(parse(text = lib_load)) # evaluate the string to load the library
41 | }
42 |
43 | # Load data ---------------------------------------------------------------
44 | cat("Load data... \n\n", sep = "")
45 | poland <- sf::st_as_sf(raster::getData('GADM', country = 'POL', level = 1))
46 | eco_farms <- fread("R/2024/week_02/eco_farms_poland.csv")
47 | eco_farms[, perc_eco := eco_farms / farms]
48 |
49 | # Join data ---------------------------------------------------------------
50 | cat("Join data... \n\n", sep = "")
51 | poland <- poland %>%
52 | left_join(eco_farms, by = "NAME_1")
53 |
54 |
55 | # Prepare data ------------------------------------------------------------
56 | # Make grid
57 | grid <- st_make_grid(poland, n = c(45,45)) %>% st_sf()
58 | grid <- st_join(grid, poland)
59 | grid <- grid %>% filter(!is.na(perc_eco))
60 | centroids <- st_centroid(grid)
61 |
62 |
63 | # Style -------------------------------------------------------------------
64 | # Color palette
65 | background <- "#0D1F2D"
66 | text <- "#FFFFFF"
67 | palette <- c("#FF3D3D", "#ffe0c8","#afffff", "#4a9d9c", "#0D6E6E")
68 |
69 | # Load fonts
70 | loadfonts(device = "win")
71 |
72 | # Fonts
73 | font_base <- "Lato"
74 | font_title <- "Lato Black"
75 |
76 | # Plot data ---------------------------------------------------------------
77 | cat("Plot data... \n\n", sep = "")
78 |
79 | plot <-
80 | ggplot() +
81 | geom_sf(data = grid, aes(fill = perc_eco), color = background) +
82 | geom_sf(data = centroids,
83 | color = alpha("black", 0.75),
84 | size = 1) +
85 | labs(fill = "% of eco-farms", title = "Ecological farms in Poland \U1F33D",
86 | caption = "Source: Główny Urząd Statystyczny\nmichal0091") +
87 | guides(fill = guide_legend(
88 | nrow = 1,
89 | title.position = "top",
90 | label.position = "bottom"
91 | )) +
92 | scale_fill_stepsn(labels = scales::percent, colors = palette,
93 | breaks = c(0, .01, .02, .04, .06, .08)) +
94 | theme_void() +
95 | theme(
96 | plot.margin = margin(1, 0.5, 1, 1, "cm"),
97 | plot.background = element_rect(fill = background, color = NA),
98 | plot.title = element_text(
99 | hjust = 0.5,
100 | vjust = 6,
101 | color = text,
102 | family = font_title,
103 | size = 28
104 | ),
105 | plot.caption = element_text(
106 | hjust = 1,
107 | vjust = -18,
108 | color = text,
109 | family = font_base,
110 | size = 8
111 | ),
112 | legend.position = "bottom",
113 | legend.title = element_text(
114 | hjust = 0.5,
115 | color = text,
116 | family = font_title
117 | ),
118 | legend.text = element_text(color = text, family = font_base)
119 | )
120 | plot
121 |
122 | # Save plot ---------------------------------------------------------------
123 | cat("Saving plot... \n\n", sep = "")
124 |
125 | ggsave(
126 | filename = "eco_farms_poland.png",
127 | path = normalizePath("R/2024/week_02/"),
128 | plot = plot,
129 | device = "png",
130 | units = "cm",
131 | width = 15.75,
132 | height = 21
133 | )
134 |
--------------------------------------------------------------------------------
/R/30DayChartChallenge2024/day_21/day_21_green_energy.R:
--------------------------------------------------------------------------------
1 | # 30DayChartChallenge2024 / day_21_green_energy
2 |
3 | # Libraries ---------------------------------------------------------------
4 | library(data.table)
5 | library(tidyverse)
6 | library(ggforce)
7 | library(ggtext)
8 | library(ggrepel)
9 | library(emojifont)
10 | library(sysfonts)
11 | library(showtext)
12 | library(patchwork)
13 | library(lubridate)
14 | library(zoo)
15 |
16 |
17 | # Source ------------------------------------------------------------------
18 | source("R/30DayChartChallenge2024/theme/styles.R")
19 | source("R/30DayChartChallenge2024/theme/theme.R")
20 |
21 |
22 | # Config ------------------------------------------------------------------
23 | cfg <-
24 | yaml::read_yaml("R/30DayChartChallenge2024/cfg/plots.yml")[["default"]]
25 | cfg_day_21 <- cfg$day_21
26 |
27 |
28 |
29 | # Data --------------------------------------------------------------------
30 | energy <- fread("R/30DayChartChallenge2024/day_21/energy.csv", dec = ",")
31 |
32 | energy <- melt(energy, id.vars = "year", variable.name = "Country", value.name = "Share")
33 | energy[, Country := factor(Country, levels = c("Portugal", "Italy", "Greece", "Spain", "EU27"),
34 | labels = c("Portugal", "Italy", "Greece", "Spain", "EU27"))]
35 | energy[, Share := Share / 100]
36 |
37 |
38 | # Plot --------------------------------------------------------------------
39 |
40 | plot <- energy[, ggplot(.SD, aes(year, Share, color = Country)) +
41 | geom_line() +
42 | geom_point() +
43 | labs(title = "Share of renewable energy in gross final energy consumption",
44 | subtitle = "Renewable energy sources in electricity in PIGS countries",
45 | x = NULL,
46 | y = "% of renewable energy",
47 | color = NULL,
48 | caption = caption_text(
49 | source_text = cfg_day_21$source,
50 | day_type = cfg_day_21$category,
51 | day_hashtag = cfg_day_21$theme,
52 | day = cfg_day_21$day,
53 | color_text_1 = c4_color_text_1,
54 | color_text_2 = c4_color_text_2
55 | )) +
56 | scale_y_continuous(labels = scales::percent_format(accuracy = 1),
57 | limits = c(0, .8),
58 | breaks = seq(0, .8, .2)) +
59 | scale_color_manual(values = c(
60 | "Portugal" = "#0D6938",
61 | "Italy" = "#ce2b37",
62 | "Greece" = "#0d5eaf",
63 | "Spain" = "#F1BF00",
64 | "EU27" = "#001489"
65 | )) +
66 | theme_my(
67 | font_regular = "josefin_regular",
68 | font_bold = "josefin_bold",
69 | font_light = "josefin_light",
70 | color_text_1 = c4_color_text_1,
71 | color_text_2 = c4_color_text_2,
72 | color_background = c4_color_background,
73 | title_size = 50
74 | ) +
75 | theme(
76 | legend.position = "bottom",
77 | plot.margin = margin(25, 25, 10, 10, "pt"),
78 | plot.caption = element_textbox_simple(
79 | size = 20,
80 | lineheight = .5,
81 | padding = margin(4, 0, 4, 0, "pt"),
82 | margin = margin(20, 0, 0, 0, "pt"),
83 | ),
84 | axis.text = element_text(
85 | size = rel(2),
86 | family = "josefin_bold",
87 | color = c4_color_text_2,
88 | margin = margin(2, 2, 2, 0, "pt")
89 | ),
90 | axis.title.y = element_text(
91 | size = 32,
92 | family = "josefin_bold",
93 | color = c4_color_text_2,
94 | margin = margin(5, 5, 5, 5, "pt"),
95 | angle = 90
96 | ),
97 | panel.grid.major = element_line(
98 | color = c4_color_text_2,
99 | linetype = "dotted",
100 | size = .3,
101 | ),
102 | axis.title.y.right = element_text(
103 | size = 32,
104 | family = "josefin_bold",
105 | color = c4_color_text_2,
106 | margin = margin(5, 5, 5, 5, "pt"),
107 | angle = -90
108 | )
109 | )
110 | ]
111 |
112 |
113 | # Save --------------------------------------------------------------------
114 | ggsave(
115 | filename = "R/30DayChartChallenge2024/day_21/day_21_green_energy.png",
116 | plot = plot,
117 | width = 3106.56,
118 | height = 1920,
119 | units = "px",
120 | dpi = 320
121 | )
122 |
123 |
--------------------------------------------------------------------------------
/R/30DayChartChallenge2024/day_15/day_15_historical.R:
--------------------------------------------------------------------------------
1 | # 30DayChartChallenge2024 / day_15_historical
2 |
3 | # Libraries ---------------------------------------------------------------
4 | library(data.table)
5 | library(tidyverse)
6 | library(ggforce)
7 | library(ggtext)
8 | library(ggrepel)
9 | library(emojifont)
10 | library(sysfonts)
11 | library(showtext)
12 | library(patchwork)
13 | library(lubridate)
14 |
15 |
16 | # Source ------------------------------------------------------------------
17 | source("R/30DayChartChallenge2024/theme/styles.R")
18 | source("R/30DayChartChallenge2024/theme/theme.R")
19 |
20 |
21 | # Config ------------------------------------------------------------------
22 | cfg <-
23 | yaml::read_yaml("R/30DayChartChallenge2024/cfg/plots.yml")[["default"]]
24 | cfg_day_15 <- cfg$day_15
25 |
26 |
27 | # Data --------------------------------------------------------------------
28 | dt <- fread("R/30DayChartChallenge2024/day_15/fredgraph.csv")
29 |
30 |
31 | # Plot --------------------------------------------------------------------
32 | dt_sub <- dt[DATE >="1950-01-01" & DATE <="1984-12-01"]
33 | dt_sub[, date_braek := fifelse(DATE <= "1970-12-01", "Yaers 1950-1970", "Years 1971-1984")]
34 |
35 |
36 | plot <- dt_sub[, ggplot(.SD, aes(UNRATE, CPIAUCSL_PC1)) +
37 | geom_point(aes(color = date_braek), size = 2.5, alpha = .5) +
38 | scale_color_manual(values = c(c3_color_accent_1, c3_color_accent_2)) +
39 | geom_smooth(
40 | data = .SD[DATE <= "1970-12-01"],
41 | method = "glm",
42 | formula = y ~ log(x),
43 | se = FALSE,
44 | color = c3_color_text_2,
45 | linewidth = 1.05,
46 | show.legend = FALSE
47 | ) +
48 | scale_x_continuous(breaks = seq(0, 12, 2), limits = c(0,12)) +
49 | scale_y_continuous(breaks = seq(-2.5, 15, 2.5), limits = c(-3,15)) +
50 | labs(
51 | title = "Fall of the Phillips Curve",
52 | subtitle = "Unemployment and Inflation in the United States\nYears 1950-1984",
53 | x = "Unemployment rate (%)",
54 | y = "Inflation rate (%)",
55 | color = NULL,
56 | caption = caption_text(
57 | source_text = cfg_day_15$source,
58 | day_type = cfg_day_15$category,
59 | day_hashtag = cfg_day_15$theme,
60 | day = cfg_day_15$day,
61 | color_text_1 = c3_color_text_2,
62 | color_text_2 = c3_color_text_1
63 | )
64 | ) +
65 | theme_my(
66 | font_regular = "redhat_regular",
67 | font_bold = "redhat_bold",
68 | font_light = "redhat_light",
69 | color_text_1 = c3_color_text_1,
70 | color_text_2 = c3_color_text_2,
71 | color_background = c3_color_background,
72 | title_size = 52
73 | ) +
74 | theme(
75 | plot.margin = margin(20, 25, 10, 20, "pt"),
76 | plot.caption = element_textbox_simple(
77 | size = 24,
78 | lineheight = .5,
79 | padding = margin(5, 5, 5, 5, "pt"),
80 | margin = margin(10, 0, 0, 0, "pt"),
81 | ),
82 | legend.position = "bottom",
83 | legend.spacing = unit(5, "pt"),
84 | legend.key.spacing = unit(5, "pt"),
85 | legend.key.height = unit(10, 'pt'),
86 | legend.key.width = unit(16.18, 'pt'),
87 | panel.grid.major = element_line(
88 | colour = c3_color_text_2,
89 | linetype = "solid",
90 | linewidth = .3
91 | ),
92 | axis.text = element_text(
93 | size = rel(1.8),
94 | family = "redhat_regular",
95 | color = c3_color_text_2,
96 | margin = margin(2, 2, 2, 0, "pt")
97 | )
98 | )]
99 |
100 |
101 | # Save --------------------------------------------------------------------
102 | ggsave(
103 | filename = "R/30DayChartChallenge2024/day_15/day_15_historical.png",
104 | plot = plot,
105 | width = 1920,
106 | height = 1920,
107 | units = "px",
108 | dpi = 320
109 | )
110 |
111 |
--------------------------------------------------------------------------------
/R/2024/week_06/median_net_wealth_by_age.csv:
--------------------------------------------------------------------------------
1 | concepto,elemento,estadistico,desglose,categoria,unidadMedida,ola,valor
2 | RIQUEZA,RIQUEZA NETA,MEDIANA,EDAD DEL CABEZA DE FAMILIA,Entre 35 y 44,Miles de Euros (),2017,65.7911983563343
3 | RIQUEZA,RIQUEZA NETA,MEDIANA,EDAD DEL CABEZA DE FAMILIA,Entre 45 y 54,Miles de Euros (),2017,116.02595494030082
4 | RIQUEZA,RIQUEZA NETA,MEDIANA,EDAD DEL CABEZA DE FAMILIA,Entre 55 y 64,Miles de Euros (),2017,176.97383595224068
5 | RIQUEZA,RIQUEZA NETA,MEDIANA,EDAD DEL CABEZA DE FAMILIA,Entre 65 y 74,Miles de Euros (),2017,183.1412059311521
6 | RIQUEZA,RIQUEZA NETA,MEDIANA,EDAD DEL CABEZA DE FAMILIA,Mayor de 75,Miles de Euros (),2017,131.38357782601955
7 | RIQUEZA,RIQUEZA NETA,MEDIANA,EDAD DEL CABEZA DE FAMILIA,Menor de 35,Miles de Euros (),2017,5.373384726314157
8 | RIQUEZA,RIQUEZA NETA,MEDIANA,EDAD DEL CABEZA DE FAMILIA,Entre 35 y 44,Miles de Euros (),2014,71.9878903031208
9 | RIQUEZA,RIQUEZA NETA,MEDIANA,EDAD DEL CABEZA DE FAMILIA,Entre 45 y 54,Miles de Euros (),2014,129.34132809317606
10 | RIQUEZA,RIQUEZA NETA,MEDIANA,EDAD DEL CABEZA DE FAMILIA,Entre 55 y 64,Miles de Euros (),2014,194.7444753810164
11 | RIQUEZA,RIQUEZA NETA,MEDIANA,EDAD DEL CABEZA DE FAMILIA,Entre 65 y 74,Miles de Euros (),2014,215.51803352346823
12 | RIQUEZA,RIQUEZA NETA,MEDIANA,EDAD DEL CABEZA DE FAMILIA,Mayor de 75,Miles de Euros (),2014,132.0591222417998
13 | RIQUEZA,RIQUEZA NETA,MEDIANA,EDAD DEL CABEZA DE FAMILIA,Menor de 35,Miles de Euros (),2014,4.959630481310039
14 | RIQUEZA,RIQUEZA NETA,MEDIANA,EDAD DEL CABEZA DE FAMILIA,Entre 35 y 44,Miles de Euros (),2011,122.77505147408418
15 | RIQUEZA,RIQUEZA NETA,MEDIANA,EDAD DEL CABEZA DE FAMILIA,Entre 45 y 54,Miles de Euros (),2011,171.9979978982872
16 | RIQUEZA,RIQUEZA NETA,MEDIANA,EDAD DEL CABEZA DE FAMILIA,Entre 55 y 64,Miles de Euros (),2011,246.70105326208423
17 | RIQUEZA,RIQUEZA NETA,MEDIANA,EDAD DEL CABEZA DE FAMILIA,Entre 65 y 74,Miles de Euros (),2011,204.170865899994
18 | RIQUEZA,RIQUEZA NETA,MEDIANA,EDAD DEL CABEZA DE FAMILIA,Mayor de 75,Miles de Euros (),2011,162.6955036593047
19 | RIQUEZA,RIQUEZA NETA,MEDIANA,EDAD DEL CABEZA DE FAMILIA,Menor de 35,Miles de Euros (),2011,72.65405756547536
20 | RIQUEZA,RIQUEZA NETA,MEDIANA,EDAD DEL CABEZA DE FAMILIA,Entre 35 y 44,Miles de Euros (),2008,171.12734298403552
21 | RIQUEZA,RIQUEZA NETA,MEDIANA,EDAD DEL CABEZA DE FAMILIA,Entre 45 y 54,Miles de Euros (),2008,225.50111318732883
22 | RIQUEZA,RIQUEZA NETA,MEDIANA,EDAD DEL CABEZA DE FAMILIA,Entre 55 y 64,Miles de Euros (),2008,308.9709906613852
23 | RIQUEZA,RIQUEZA NETA,MEDIANA,EDAD DEL CABEZA DE FAMILIA,Entre 65 y 74,Miles de Euros (),2008,219.40727257886752
24 | RIQUEZA,RIQUEZA NETA,MEDIANA,EDAD DEL CABEZA DE FAMILIA,Mayor de 75,Miles de Euros (),2008,173.04273277681384
25 | RIQUEZA,RIQUEZA NETA,MEDIANA,EDAD DEL CABEZA DE FAMILIA,Menor de 35,Miles de Euros (),2008,85.17145631322224
26 | RIQUEZA,RIQUEZA NETA,MEDIANA,EDAD DEL CABEZA DE FAMILIA,Entre 35 y 44,Miles de Euros (),2005,193.2520578067752
27 | RIQUEZA,RIQUEZA NETA,MEDIANA,EDAD DEL CABEZA DE FAMILIA,Entre 45 y 54,Miles de Euros (),2005,268.6937365674177
28 | RIQUEZA,RIQUEZA NETA,MEDIANA,EDAD DEL CABEZA DE FAMILIA,Entre 55 y 64,Miles de Euros (),2005,281.520113697285
29 | RIQUEZA,RIQUEZA NETA,MEDIANA,EDAD DEL CABEZA DE FAMILIA,Entre 65 y 74,Miles de Euros (),2005,221.67549879509264
30 | RIQUEZA,RIQUEZA NETA,MEDIANA,EDAD DEL CABEZA DE FAMILIA,Mayor de 75,Miles de Euros (),2005,165.49992649535392
31 | RIQUEZA,RIQUEZA NETA,MEDIANA,EDAD DEL CABEZA DE FAMILIA,Menor de 35,Miles de Euros (),2005,87.24643017747626
32 | RIQUEZA,RIQUEZA NETA,MEDIANA,EDAD DEL CABEZA DE FAMILIA,Entre 35 y 44,Miles de Euros (),2002,117.66751414777336
33 | RIQUEZA,RIQUEZA NETA,MEDIANA,EDAD DEL CABEZA DE FAMILIA,Entre 45 y 54,Miles de Euros (),2002,163.03078947896952
34 | RIQUEZA,RIQUEZA NETA,MEDIANA,EDAD DEL CABEZA DE FAMILIA,Entre 55 y 64,Miles de Euros (),2002,164.1573385758243
35 | RIQUEZA,RIQUEZA NETA,MEDIANA,EDAD DEL CABEZA DE FAMILIA,Entre 65 y 74,Miles de Euros (),2002,131.8997640776074
36 | RIQUEZA,RIQUEZA NETA,MEDIANA,EDAD DEL CABEZA DE FAMILIA,Mayor de 75,Miles de Euros (),2002,98.99752320626216
37 | RIQUEZA,RIQUEZA NETA,MEDIANA,EDAD DEL CABEZA DE FAMILIA,Menor de 35,Miles de Euros (),2002,65.14499235512984
38 | RIQUEZA,RIQUEZA NETA,MEDIANA,EDAD DEL CABEZA DE FAMILIA,Entre 35 y 44,Miles de Euros (),2020,70.0
39 | RIQUEZA,RIQUEZA NETA,MEDIANA,EDAD DEL CABEZA DE FAMILIA,Entre 45 y 54,Miles de Euros (),2020,116.48084
40 | RIQUEZA,RIQUEZA NETA,MEDIANA,EDAD DEL CABEZA DE FAMILIA,Entre 55 y 64,Miles de Euros (),2020,160.6502
41 | RIQUEZA,RIQUEZA NETA,MEDIANA,EDAD DEL CABEZA DE FAMILIA,Entre 65 y 74,Miles de Euros (),2020,197.9254
42 | RIQUEZA,RIQUEZA NETA,MEDIANA,EDAD DEL CABEZA DE FAMILIA,Mayor de 75,Miles de Euros (),2020,165.18779999999998
43 | RIQUEZA,RIQUEZA NETA,MEDIANA,EDAD DEL CABEZA DE FAMILIA,Menor de 35,Miles de Euros (),2020,23.9686
44 |
--------------------------------------------------------------------------------
/R/30DayChartChallenge2024/day_19/day_19_dinosaurs.R:
--------------------------------------------------------------------------------
1 | # 30DayChartChallenge2024 / day_19_dinosaurs
2 |
3 | # Libraries ---------------------------------------------------------------
4 | library(data.table)
5 | library(tidyverse)
6 | library(ggforce)
7 | library(ggtext)
8 | library(ggrepel)
9 | library(emojifont)
10 | library(sysfonts)
11 | library(showtext)
12 | library(patchwork)
13 | library(lubridate)
14 | library(zoo)
15 |
16 |
17 | # Source ------------------------------------------------------------------
18 | source("R/30DayChartChallenge2024/theme/styles.R")
19 | source("R/30DayChartChallenge2024/theme/theme.R")
20 |
21 |
22 | # Config ------------------------------------------------------------------
23 | cfg <-
24 | yaml::read_yaml("R/30DayChartChallenge2024/cfg/plots.yml")[["default"]]
25 | cfg_day_19 <- cfg$day_19
26 |
27 |
28 | # Data --------------------------------------------------------------------
29 | dinos <- fread("R/30DayChartChallenge2024/day_19/multiTimeline.csv")
30 |
31 | setnames(dinos,
32 | old = c("Mes", "dinosaurs: (Todo el mundo)"),
33 | new = c("date", "searches"))
34 |
35 | dinos[, date := lubridate::as_date(as.yearmon(date, format = "%Y-%m"))]
36 |
37 |
38 | # 2009 - Ice Age: Dawn of the Dinosaurs - 1 July 2009
39 | # 2013 - Walking with Dinosaurs - 20 December 2013
40 | # 2015 - Jurassic World - 12 June 2015
41 | # 2018 - Jurassic World: Fallen Kingdom - 22 June 2018
42 | # 2022 - Jurassic World: Dominion - 10 June 2022
43 |
44 | labels <- data.table(
45 | date = as.Date(c("2009-07-01", "2013-12-01", "2015-06-01", "2018-06-01", "2022-07-01")),
46 | label = c("Ice Age: Dawn of the Dinosaurs", "Walking with Dinosaurs", "Jurassic World", "Jurassic World: Fallen Kingdom", "Jurassic World: Dominion")
47 | )
48 | labels <- merge(labels, dinos, by = "date")
49 |
50 | # Plot --------------------------------------------------------------------
51 |
52 | plot <- dinos[, ggplot(.SD, aes(date, searches)) +
53 | geom_line(color = c4_color_set_1) +
54 | geom_point(data = .SD[date %in% labels$date], color = c4_color_set_1) +
55 | geom_text(
56 | data = labels,
57 | aes(label = label, x = date, y = searches),
58 | hjust = 0,
59 | vjust = -1,
60 | nudge_x = 1,
61 | family = "josefin_bold",
62 | color = c4_color_text_1,
63 | size = rel(9)
64 | ) +
65 | scale_x_date(
66 | date_breaks = "1 year",
67 | date_labels = "%Y",
68 | limits = c(as.Date("2005-01-01"), as.Date("2025-01-01")),
69 | expand = c(0, 0)
70 | ) +
71 | scale_y_continuous(
72 | expand = c(0, 0),
73 | limits = c(0, 100),
74 | labels = scales::number_format(accuracy = 1)
75 | ) +
76 | labs(
77 | title = "Dinosaurs searches on Google",
78 | subtitle = "2005 - 2024",
79 | x = "Year",
80 | y = "Interest over time",
81 | caption = caption_text(
82 | source_text = cfg_day_19$source,
83 | day_type = cfg_day_19$category,
84 | day_hashtag = cfg_day_19$theme,
85 | day = cfg_day_19$day,
86 | color_text_1 = c4_color_text_1,
87 | color_text_2 = c4_color_text_2
88 | )
89 | ) +
90 | theme_my(
91 | font_regular = "josefin_regular",
92 | font_bold = "josefin_bold",
93 | font_light = "josefin_light",
94 | color_text_1 = c4_color_text_1,
95 | color_text_2 = c4_color_text_2,
96 | color_background = c4_color_background,
97 | title_size = 50
98 | ) +
99 | theme(
100 | axis.title = element_blank(),
101 | legend.position = "none"
102 | ) +
103 | coord_cartesian(clip = "off") +
104 | theme(
105 | plot.margin = margin(25, 25, 10, 10, "pt"),
106 | plot.caption = element_textbox_simple(
107 | size = 20,
108 | lineheight = .5,
109 | padding = margin(4, 0, 4, 0, "pt"),
110 | margin = margin(20, 0, 0, 0, "pt"),
111 | ),
112 | axis.text = element_text(
113 | size = rel(2),
114 | family = "josefin_bold",
115 | color = c4_color_text_2,
116 | margin = margin(2, 2, 2, 0, "pt")
117 | ),
118 | axis.title.y = element_text(
119 | size = rel(3),
120 | family = "josefin_bold",
121 | color = c4_color_text_2,
122 | margin = margin(5, 5, 5, 5, "pt"),
123 | angle = 90
124 | ),
125 | panel.grid.major = element_line(
126 | color = c4_color_text_2,
127 | linetype = "dotted",
128 | size = .3,
129 |
130 | )
131 | )]
132 |
133 |
134 | # Save --------------------------------------------------------------------
135 | ggsave(
136 | filename = "R/30DayChartChallenge2024/day_19/day_19_dinosaurs.png",
137 | plot = plot,
138 | width = 3106.56,
139 | height = 1920,
140 | units = "px",
141 | dpi = 320
142 | )
143 |
144 |
--------------------------------------------------------------------------------
/R/30DayChartChallenge2024/day_18/day_18_asian_development_bank.R:
--------------------------------------------------------------------------------
1 | # 30DayChartChallenge2024 / day_18_asian_development_bank
2 |
3 | # Libraries ---------------------------------------------------------------
4 | library(data.table)
5 | library(tidyverse)
6 | library(ggforce)
7 | library(ggtext)
8 | library(ggrepel)
9 | library(emojifont)
10 | library(sysfonts)
11 | library(showtext)
12 | library(patchwork)
13 | library(lubridate)
14 | library(geomnet)
15 | library(ggnetwork)
16 | library(igraph)
17 |
18 |
19 | # Source ------------------------------------------------------------------
20 | source("R/30DayChartChallenge2024/theme/styles.R")
21 | source("R/30DayChartChallenge2024/theme/theme.R")
22 |
23 |
24 | # Config ------------------------------------------------------------------
25 | cfg <-
26 | yaml::read_yaml("R/30DayChartChallenge2024/cfg/plots.yml")[["default"]]
27 | cfg_day_18 <- cfg$day_18
28 |
29 |
30 | # Data --------------------------------------------------------------------
31 | exch <- fread("R/30DayChartChallenge2024/day_18/exchange.csv", dec = ",")
32 | library(readxl)
33 | KIDB <- read_excel("R/30DayChartChallenge2024/day_18/KIDB.xlsx") %>%
34 | as.data.table()
35 |
36 | KIDB <- KIDB[Economy %in% exch[, country]]
37 | KIDB <- KIDB[, .(int_tourism_receipts_pc = 1000 * `2022`[Indicator == "International Tourism Receipts ($ million)"] / `2022`[Indicator == "Total population"],
38 | gdp_pc_lp = `2022`[Indicator == "GDP at current prices"] / `2022`[Indicator == "Total population"]), by = .(country = Economy)]
39 | KIDB <- na.omit(KIDB)
40 | KIDB <- merge(KIDB, exch, by = "country")
41 | KIDB[, gdp_pc_usd := gdp_pc_lp / exchange_rate]
42 |
43 |
44 | # Plot --------------------------------------------------------------------
45 |
46 | plot <- KIDB[, ggplot(.SD, aes(x = gdp_pc_usd, y = int_tourism_receipts_pc)) +
47 | geom_point(aes(color = region), size = 3) +
48 | geom_text_repel(aes(label = country), size = rel(8),
49 | box.padding = 1, point.padding = 1,
50 | max.overlaps = 12,
51 | family = "redhat_regular") +
52 | scale_x_log10(expand = c(0.1, 0.1),
53 | labels = scales::label_dollar(accuracy = 1000L)) +
54 | scale_y_log10(expand = c(0.1, 0.5),
55 |
56 | labels = scales::label_dollar(accuracy = 1000L)) +
57 | scale_color_manual(values = c("#d99058",
58 | "#02517a",
59 | "#9556eb",
60 | "#c0dccd")) +
61 | labs(
62 | title = "International Tourism Receipts vs\nGDP per capita",
63 | subtitle = "Asian Development Bank 2022",
64 | x = "GDP per capita (USD)",
65 | y = "International Tourism Receipts per capita (USD thousand)",
66 | color = NULL,
67 | caption = caption_text(
68 | source_text = cfg_day_18$source,
69 | day_type = cfg_day_18$category,
70 | day_hashtag = cfg_day_18$theme,
71 | day = cfg_day_18$day,
72 | color_text_1 = c3_color_text_1,
73 | color_text_2 = c3_color_text_2
74 | )
75 | ) +
76 | theme_my(
77 | font_regular = "redhat_regular",
78 | font_bold = "redhat_bold",
79 | font_light = "redhat_light",
80 | color_text_1 = c3_color_text_1,
81 | color_text_2 = c3_color_text_2,
82 | color_background = c3_color_background,
83 | title_size = 50
84 | ) +
85 | theme(
86 | plot.margin = margin(20, 60, 10, 20, "pt"),
87 | plot.caption = element_textbox_simple(
88 | size = 20,
89 | lineheight = .5,
90 | padding = margin(4, 0, 4, 0, "pt"),
91 | margin = margin(20, 0, 0, 0, "pt"),
92 | ),
93 | legend.position = "bottom",
94 | legend.spacing = unit(2.5, "pt"),
95 | legend.key.spacing = unit(2.5, "pt"),
96 | legend.key.height = unit(8, 'pt'),
97 | legend.key.width = unit(12.944, 'pt'),
98 | legend.title = element_text(hjust = 0),
99 | panel.grid.major = element_line(
100 | colour = c3_color_text_2,
101 | linetype = "dashed",
102 | linewidth = .3
103 | ),
104 | axis.text = element_text(
105 | size = rel(1.8),
106 | family = "redhat_regular",
107 | color = c3_color_text_2,
108 | margin = margin(2, 2, 2, 0, "pt")
109 | )
110 | )]
111 |
112 |
113 | # Save plot ---------------------------------------------------------------
114 | ggsave(
115 | filename = "R/30DayChartChallenge2024/day_18/day_18_asian_development_bank.png",
116 | plot = plot,
117 | width = 1920,
118 | height = 1920,
119 | units = "px",
120 | dpi = 320
121 | )
122 |
123 |
124 |
125 |
--------------------------------------------------------------------------------
/R/30DayChartChallenge2024/day_03/day_3_makeover.R:
--------------------------------------------------------------------------------
1 | # 30DayChartChallenge2024 / day_3_makeover
2 |
3 | # Libraries ---------------------------------------------------------------
4 | library(data.table)
5 | library(ggplot2)
6 | library(ggforce)
7 | library(ggtext)
8 | library(emojifont)
9 | library(sysfonts)
10 | library(showtext)
11 | library(ggpubr)
12 |
13 |
14 | # Source ------------------------------------------------------------------
15 | source("R/30DayChartChallenge2024/theme/styles.R")
16 | source("R/30DayChartChallenge2024/theme/theme.R")
17 |
18 |
19 | # Config ------------------------------------------------------------------
20 | cfg <-
21 | yaml::read_yaml("R/30DayChartChallenge2024/cfg/plots.yml")[["default"]]
22 | cfg_day_3 <- cfg$day_3
23 |
24 | # Data --------------------------------------------------------------------
25 | # From chart
26 | # Values less than 0.5 percent are indicated by an asterisk (*)
27 | #'
28 | #'Q11. To the best of your knowledge, will the overuse of antibiotics lead to
29 | #' (INSERT ITEM), will the overuse of antibiotics not lead to this, or do
30 | #' you not know enough to say? How about (INSERT NEXT ITEM)?
31 | #' (IF NECESSARY: Will the overuse of antibiotics lead to (INSERT ITEM), will
32 | #' the overuse of antibiotics not lead to this, or do you not know enough to say?)
33 | #' (scramble items a-f)
34 | #' c. The spread of measles or other contagious viruses 26 39 35 *
35 | #'
36 |
37 | dt <- data.table(
38 | correct = c("Correct", "Incorrect", "Incorrect"),
39 | anwser = c("No", "Yes", "Don't know enough to say"),
40 | value = c(0.39, 0.26, 0.35)
41 | )
42 | dt[, label := paste0(correct, " ", sprintf("%2.0f", 100 * sum(value)), "%"), by = correct]
43 |
44 | # Plot --------------------------------------------------------------------
45 | color_text_2 <- "#2948FF"
46 | title_text <- glue::glue(
47 | "Most of the public
48 | unaware, antibiotic resistance
is
49 | unrelated to the outbreak of viruses such as measles
50 | "
51 | )
52 |
53 |
54 | plot <- dt %>%
55 | ggplot(aes(value, anwser, fill = anwser)) +
56 | geom_col(just = 0.5, size = 1) +
57 | facet_grid(label ~ ., scales = "free", space = "free") +
58 | geom_text(
59 | aes(label = paste0(" ", sprintf("%2.0f", 100 * value), "% "),
60 | hjust = -.1),
61 | vjust = "center",
62 | color = color_text_1,
63 | size = rel(7),
64 | fontface = "bold",
65 | family = "inter_regular"
66 | ) +
67 | geom_text(
68 | aes(x = 0.005,
69 | label = anwser),
70 | color = color_background,
71 | hjust = "left",
72 | vjust = "center",
73 | size = rel(9),
74 | fontface = "bold",
75 | family = "inter_regular"
76 | ) +
77 | scale_x_continuous(
78 | name = NULL,
79 | expand = c(0, 0),
80 | limits = c(0, 0.5),
81 | guide = "none"
82 | ) +
83 | scale_y_discrete(guide = "none") +
84 | scale_color_manual(values = c(color_text_1, color_background),
85 | guide = "none") +
86 | scale_fill_manual(
87 | values = c(
88 | "No" = "#537c78",
89 | "Yes" = "#cc222b",
90 | "Don't know enough to say" = "#f15b4c"
91 | ),
92 | guide = "none"
93 | ) +
94 | labs(
95 | title = title_text,
96 | subtitle = "To the best of your knowledge, will the overuse of antibiotics\nlead to the spread of measles or other contagious viruses?",
97 | x = NULL,
98 | y = NULL,
99 | caption = glue::glue(
100 | "* Refused less than 0.5%
",
101 | caption_text(
102 | source_text = cfg_day_3$source,
103 | day_type = cfg_day_3$category,
104 | day_hashtag = cfg_day_3$theme,
105 | day = cfg_day_3$day,
106 | color_text_2 = color_text_2
107 | )
108 | )
109 | ) +
110 | theme_my(color_text_2 = color_text_2) +
111 | theme(
112 | strip.background = element_rect(fill = color_text_1, color = color_background),
113 | strip.text = element_text(
114 | color = color_background,
115 | family = "inter_regular",
116 | hjust = 0.5,
117 | margin = margin(.25, .25, .25, .25, "line"),
118 | face = "bold",
119 | angle = -90,
120 | ),
121 | panel.grid.major = element_blank(),
122 | panel.spacing = unit(0.5, "lines"),
123 | plot.title = element_markdown(
124 | size = 26,
125 | family = "inter_bold",
126 | face = "bold",
127 | hjust = 0,
128 | vjust = 4.5,
129 | lineheight = .34,
130 | margin = margin(.2, .2, 1, .2, "lines")
131 | ),
132 | plot.margin = margin(.5, .5, .5, .5, "lines"),
133 | )
134 |
135 |
136 | # Save --------------------------------------------------------------------
137 | ggsave(
138 | filename = "day_3_makeover.png",
139 | path = normalizePath("R/30DayChartChallenge2024/day_03"),
140 | plot = plot,
141 | device = "png",
142 | units = "px",
143 | width = 1080,
144 | height = 1080,
145 | dpi = 320
146 | )
147 |
148 |
149 |
--------------------------------------------------------------------------------
/R/30DayChartChallenge2024/day_20/day_20_correlation.R:
--------------------------------------------------------------------------------
1 | # 30DayChartChallenge2024 / day_20_correlation
2 |
3 | # Libraries ---------------------------------------------------------------
4 | library(data.table)
5 | library(tidyverse)
6 | library(ggforce)
7 | library(ggtext)
8 | library(ggrepel)
9 | library(emojifont)
10 | library(sysfonts)
11 | library(showtext)
12 | library(patchwork)
13 | library(lubridate)
14 | library(zoo)
15 |
16 |
17 | # Source ------------------------------------------------------------------
18 | source("R/30DayChartChallenge2024/theme/styles.R")
19 | source("R/30DayChartChallenge2024/theme/theme.R")
20 |
21 |
22 | # Config ------------------------------------------------------------------
23 | cfg <-
24 | yaml::read_yaml("R/30DayChartChallenge2024/cfg/plots.yml")[["default"]]
25 | cfg_day_20 <- cfg$day_20
26 |
27 |
28 | # Data --------------------------------------------------------------------
29 | cpi_brent <- fread("R/30DayChartChallenge2024/day_20/cpi_brent.csv", dec = ",")
30 | cpi_brent[, y_m := as.Date(as.yearmon(y_m, "%YM%m"))]
31 | cpi_brent[, cpi := cpi / 100]
32 |
33 |
34 | # Plot --------------------------------------------------------------------
35 |
36 | b <- diff(cpi_brent[, c(min(brent_crude_oil_12m), max(brent_crude_oil_12m))]) /
37 | diff(cpi_brent[, c(min(cpi), max(cpi))])
38 |
39 | plot <- cpi_brent[, ggplot(.SD, aes(y_m)) +
40 | geom_line(aes(y_m, brent_crude_oil_12m, color = "brent")) +
41 | geom_line(aes(y_m, cpi * b, color = "cpi")) +
42 | scale_y_continuous(labels = scales::percent,
43 | limits = c(min(brent_crude_oil_12m), max(brent_crude_oil_12m)),
44 | name = "Brent Crude Oil price (yoy)",
45 | sec.axis = sec_axis(~ (. )/b, name = "CPI Spain (yoy)",
46 | labels = scales::percent)) +
47 | scale_color_manual(values = c("cpi" = c4_color_set_1, "brent" = c4_color_set_2)) +
48 | annotate("text", x = as.Date("2022-01-01"),
49 | y = -0.5,
50 | label = paste("ρ:", round(cor(cpi, brent_crude_oil_12m, use = "complete.obs"), 2)),
51 | color = c4_color_text_2,
52 | hjust = 0,
53 | size = rel(10),
54 | family = "roboto_bold") +
55 | labs(
56 | title = "CPI and Brent Crude Oil year-on-year change",
57 | subtitle = "Correlation between Spanish CPI and the Brent Crude Oil Price",
58 | x = "Year",
59 | y = "Value",
60 | color = NULL,
61 | caption = caption_text(
62 | source_text = cfg_day_20$source,
63 | day_type = cfg_day_20$category,
64 | day_hashtag = cfg_day_20$theme,
65 | day = cfg_day_20$day,
66 | color_text_1 = c4_color_text_1,
67 | color_text_2 = c4_color_text_2
68 | )
69 | ) +
70 | theme_my(
71 | font_regular = "josefin_regular",
72 | font_bold = "josefin_bold",
73 | font_light = "josefin_light",
74 | color_text_1 = c4_color_text_1,
75 | color_text_2 = c4_color_text_2,
76 | color_background = c4_color_background,
77 | title_size = 50
78 | ) +
79 | theme(
80 | legend.position = "bottom",
81 | plot.margin = margin(25, 25, 10, 10, "pt"),
82 | plot.caption = element_textbox_simple(
83 | size = 20,
84 | lineheight = .5,
85 | padding = margin(4, 0, 4, 0, "pt"),
86 | margin = margin(20, 0, 0, 0, "pt"),
87 | ),
88 | axis.text = element_text(
89 | size = rel(2),
90 | family = "josefin_bold",
91 | color = c4_color_text_2,
92 | margin = margin(2, 2, 2, 0, "pt")
93 | ),
94 | axis.title.y = element_text(
95 | size = 32,
96 | family = "josefin_bold",
97 | color = c4_color_text_2,
98 | margin = margin(5, 5, 5, 5, "pt"),
99 | angle = 90
100 | ),
101 | panel.grid.major = element_line(
102 | color = c4_color_text_2,
103 | linetype = "dotted",
104 | size = .3,
105 | ),
106 | axis.title.y.right = element_text(
107 | size = 32,
108 | family = "josefin_bold",
109 | color = c4_color_text_2,
110 | margin = margin(5, 5, 5, 5, "pt"),
111 | angle = -90
112 | )
113 | )
114 | ]
115 |
116 |
117 | # Save --------------------------------------------------------------------
118 | ggsave(
119 | filename = "R/30DayChartChallenge2024/day_20/day_20_correlation.png",
120 | plot = plot,
121 | width = 3106.56,
122 | height = 1920,
123 | units = "px",
124 | dpi = 320
125 | )
126 |
127 |
128 |
129 |
130 |
--------------------------------------------------------------------------------
/R/30DayChartChallenge2024/day_27/day_27_GoodBad.R:
--------------------------------------------------------------------------------
1 | # 30DayChartChallenge2024 / day_27_GoodBad
2 |
3 | # Libraries ---------------------------------------------------------------
4 | library(data.table)
5 | library(tidyverse)
6 | library(ggforce)
7 | library(ggtext)
8 | library(ggrepel)
9 | library(emojifont)
10 | library(sysfonts)
11 | library(showtext)
12 | library(ggplot2)
13 | library(tidyverse)
14 | library(mlmhelpr)
15 |
16 |
17 | # Source ------------------------------------------------------------------
18 | source("R/30DayChartChallenge2024/theme/styles.R")
19 | source("R/30DayChartChallenge2024/theme/theme.R")
20 |
21 |
22 | # Config ------------------------------------------------------------------
23 | cfg <-
24 | yaml::read_yaml("R/30DayChartChallenge2024/cfg/plots.yml")[["default"]]
25 | cfg_day_27 <- cfg$day_27
26 |
27 |
28 | # Data --------------------------------------------------------------------
29 | dt <-
30 | fread("R/30DayChartChallenge2024/day_27/forecast.csv", dec = ",")
31 | dt <-
32 | melt(dt,
33 | id.vars = "previsiones",
34 | variable.name = "year",
35 | value.name = "forecast")
36 | dt[, year := fifelse(year == "pib_2025", "GDP 2025 forecast", "GDP 2024 forecast")]
37 | dt[, forecast := forecast / 100]
38 | dt[, x_jit := jitter(as.numeric(as.factor(year)), factor = .5)]
39 |
40 |
41 | # Get min forecast of each year
42 | min_forecast <-
43 | dt[, .(x_jit = x_jit[forecast == min(forecast)], forecast = min(forecast)), year]
44 | max_forecast <-
45 | dt[, .(x_jit = x_jit[forecast == max(forecast)], forecast = max(forecast)), year]
46 | max_forecast <- max_forecast[, first(.SD), year]
47 |
48 | plot <- dt[, ggplot(.SD, aes(year, forecast)) +
49 | geom_boxplot(
50 | width = .5,
51 | outliers = FALSE,
52 | staplewidth = 0.5,
53 | fill = NA,
54 | color = "#1f2937"
55 | ) +
56 |
57 | geom_point(aes(x_jit, forecast), color = "#4b5563") +
58 | geom_text_repel(
59 | data = min_forecast,
60 | aes(x_jit, forecast, label = paste0(
61 | "Worst: ", scales::percent(forecast, accuracy = .01)
62 | )),
63 | family = "inter_bold",
64 | size = rel(12),
65 | direction = "y",
66 | color = "#030712",
67 | segment.size = 0.5,
68 | nudge_x = 0.5,
69 | nudge_y = c(0.001, 0.0015),
70 | segment.curvature = 0.2,
71 | segment.color = "#1f2937"
72 | ) +
73 | geom_text_repel(
74 | data = max_forecast,
75 | aes(x_jit, forecast, label = paste0(
76 | "Best: ", scales::percent(forecast, accuracy = .01)
77 | )),
78 | family = "inter_bold",
79 | size = rel(12),
80 | direction = "y",
81 | color = "#030712",
82 | segment.size = 0.5,
83 | nudge_x = 0.5,
84 | nudge_y = c(0.0015,-0.001),
85 | segment.curvature = 0.2,
86 | segment.color = "#1f2937"
87 | ) +
88 |
89 | scale_y_continuous(labels = scales::percent) +
90 | labs(
91 | title = "GDP Forecast 2024 and 2025",
92 | subtitle = "for Spanish economy",
93 | x = NULL,
94 | y = NULL,
95 | caption = caption_text(
96 | source = cfg_day_27$source,
97 | day_type = cfg_day_27$category,
98 | day_hashtag = cfg_day_27$theme,
99 | day = cfg_day_27$day,
100 | color_text_1 = "#030712",
101 | color_text_2 = "#1f2937"
102 | )
103 | ) +
104 | theme_my(
105 | font_regular = "inter_regular",
106 | font_bold = "inter_bold",
107 | font_light = "inter_light",
108 | color_text_1 = "#030712",
109 | color_text_2 = "#1f2937",
110 | color_background = "#d1d5db",
111 | title_size = 48
112 | ) +
113 | theme(
114 | legend.position = "bottom",
115 | axis.text = element_text(
116 | family = "roboto_regular",
117 | size = 26,
118 | hjust = .5
119 | ),
120 | plot.margin = margin(25, 45, 25, 25, "pt"),
121 | plot.title.position = "plot",
122 | plot.caption.position = "plot",
123 | plot.caption = element_textbox_simple(
124 | size = 26,
125 | lineheight = .5,
126 | padding = margin(0, 0, 0, 0, "pt"),
127 | margin = margin(25, 0, 0, 0, "pt"),
128 | )
129 | )]
130 |
131 |
132 |
133 | # Save --------------------------------------------------------------------
134 | ggsave(
135 | "R/30DayChartChallenge2024/day_27/day_27_GoodBad.png",
136 | plot,
137 | width = 1920,
138 | height = 1920,
139 | units = "px",
140 | dpi = 320
141 | )
142 |
143 |
--------------------------------------------------------------------------------
/R/30DayChartChallenge2025/category_4_timeseries/day_22_stars/day_22.R:
--------------------------------------------------------------------------------
1 | # --- Day 22: Stars (Confirmed Exoplanet Discoveries Over Time) ---
2 | # #30DayChartChallenge 2025
3 | # Autor: Michal Kinel (Datos: NASA Exoplanet Archive)
4 | # Número acumulado de exoplanetas confirmados descubiertos por año.
5 |
6 | # --- 1. Cargar Librerías ---
7 | library(ggplot2)
8 | library(data.table)
9 | library(yaml)
10 | library(showtext)
11 | library(ggtext)
12 | library(scales)
13 | library(lubridate)
14 | # --- 2. Cargar Configuración, Temas y Utilidades ---
15 | themes_file <- "R/30DayChartChallenge2025/themes_30DCC2025.R"
16 | utils_file <- "R/30DayChartChallenge2025/utils.R"
17 | config_file <- "R/30DayChartChallenge2025/30DayChartChallenge2025.yml"
18 | font_path_fa <- "fonts/fa-brands-400.ttf"
19 | output_path <- "R/30DayChartChallenge2025/plots/"
20 |
21 | # Verificar existencia de archivos y cargar
22 | source(themes_file)
23 | source(utils_file)
24 | config <- read_yaml(config_file)
25 |
26 | # --- 3. Configurar Fuentes ---
27 | setup_fonts(fa_brands_path = font_path_fa) # Carga "Lato"
28 |
29 | # --- 4. Cargar y Preparar Datos de Exoplanetas ---
30 |
31 | data_file <- "R/30DayChartChallenge2025/data/nasa_exoplanets_confirmed.csv"
32 |
33 | if (!file.exists(data_file)) {
34 | stop("Archivo CSV de exoplanetas no encontrado en: ", data_file,
35 | "\nDescárgalo desde https://exoplanetarchive.ipac.caltech.edu/ (Confirmed Planets Table).")
36 | }
37 |
38 | message("Cargando datos de exoplanetas desde: ", data_file)
39 | exoplanet_dt <- fread(data_file, skip = 99, header = TRUE)
40 |
41 | message("Datos cargados. ", nrow(exoplanet_dt), " planetas confirmados iniciales.")
42 | print(head(exoplanet_dt))
43 | print(names(exoplanet_dt)) # <- ¡Verifica el nombre exacto de la columna del año!
44 |
45 | # --- Procesamiento ---
46 | # Asumiendo que la columna se llama 'disc_year'
47 | col_year <- "disc_year"
48 | if (!col_year %in% names(exoplanet_dt)) {
49 | # Intenta con otros nombres comunes si falla
50 | alt_col_year <- names(exoplanet_dt)[grep("discoveryyear|disc_year", names(exoplanet_dt), ignore.case = TRUE)][1]
51 | if(!is.na(alt_col_year)) {
52 | warning("Columna '", col_year, "' no encontrada, usando '", alt_col_year, "' en su lugar.")
53 | col_year <- alt_col_year
54 | } else {
55 | stop("No se encontró una columna con el año de descubrimiento. Revisa el CSV.")
56 | }
57 | }
58 |
59 |
60 | # Asegurar que el año es numérico y válido
61 | exoplanet_dt[, Year := as.numeric(get(col_year))]
62 | exoplanet_clean_dt <- exoplanet_dt[!is.na(Year) & Year > 0] # Filtrar años inválidos
63 |
64 | # Contar descubrimientos por año
65 | discoveries_per_year <- exoplanet_clean_dt[, .N, by = .(Year)][order(Year)]
66 |
67 | # Calcular el acumulado
68 | discoveries_per_year[, Cumulative_Discoveries := cumsum(N)]
69 |
70 | message("Datos agregados por año. Rango: ", min(discoveries_per_year$Year), "-", max(discoveries_per_year$Year))
71 | print(tail(discoveries_per_year))
72 |
73 | # --- 5. Crear Gráfico de Líneas (Acumulado Exoplanetas) ---
74 |
75 | # Definir textos
76 | source_text_day22 <- "Fuente: NASA Exoplanet Archive (exoplanetarchive.ipac.caltech.edu)"
77 | plot_title <- "La Explosión en el Descubrimiento de Exoplanetas"
78 | current_year <- year(Sys.Date())
79 | plot_subtitle <- paste0("Número acumulado de exoplanetas confirmados descubiertos por año.\n",
80 | "Nota: El dato de ", current_year, " incluye descubrimientos hasta la fecha actual (",
81 | format(Sys.Date(), "%b %Y"), ").")
82 |
83 |
84 | # Generar caption
85 | caption_day22 <- generate_caption(
86 | day = 22,
87 | source_text = source_text_day22,
88 | config = config,
89 | color_text_source = "#5c5c5c",
90 | color_text_author = "#757de8"
91 |
92 | )
93 |
94 | # Colores y tema
95 | bg_col <- "#F2F2F2"
96 | # Usar un color de la paleta social (ej. el primario índigo o el acento rosa)
97 | line_color <- challenge_palettes$week4_social['pink']
98 |
99 | # Crear el gráfico de línea acumulada
100 | gg_day22 <- ggplot(discoveries_per_year, aes(x = Year, y = Cumulative_Discoveries)) +
101 | geom_line(color = line_color, linewidth = 1.3) +
102 | geom_point(color = line_color, size = 1.5, shape = 21, fill = bg_col, stroke = 0.5) + # Puntos opcionales
103 |
104 | # Formato de ejes
105 | scale_y_continuous(labels = scales::label_comma(), expand = expansion(mult=c(0, 0.05))) + # Números grandes con comas
106 | scale_x_continuous() + # Ajusta breaks si es necesario
107 |
108 | # Aplicar tema
109 | theme_week4_social(base_family = "Lato", base_size = 10) +
110 |
111 | # Etiquetas y caption
112 | labs(
113 | title = plot_title,
114 | subtitle = plot_subtitle,
115 | x = "Año de Descubrimiento",
116 | y = "Número Acumulado de Exoplanetas Confirmados",
117 | caption = caption_day22
118 | ) +
119 | theme(legend.position = "none")
120 |
121 |
122 | # --- 6. Guardar Gráfico ---
123 | output_file <- file.path(output_path, "day_22_stars_exoplanets.png")
124 | ggsave(
125 | filename = output_file,
126 | plot = gg_day22,
127 | width = 1200, height = 1200, units = "px", dpi = 150, bg = bg_col # Apaisado
128 | )
129 |
130 | message("Gráfico del Día 22 (Stars Exoplanets) guardado en: ", normalizePath(output_file, mustWork = FALSE))
131 |
132 | # --- Fin day_22_stars_exoplanets.R ---
--------------------------------------------------------------------------------
/R/30DayChartChallenge2025/category_1_comparisons/day_1_fractions/day_1.R:
--------------------------------------------------------------------------------
1 | # --- Day 1: Fractions (Régimen Tenencia Vivienda por Edad) ---
2 | # #30DayChartChallenge 2025
3 | # Autor: Michal Kinel (Datos: INE)
4 |
5 | # --- 1. Cargar Librerías ---
6 | library(ggplot2)
7 | library(dplyr)
8 | library(data.table) # Usaremos fread por eficiencia y manejo de decimales/NA
9 | library(yaml)
10 | library(showtext)
11 | library(ggtext)
12 | library(scales)
13 |
14 | # --- 2. Cargar Configuración, Temas y Utilidades ---
15 | themes_file <- "R/30DayChartChallenge2025/themes_30DCC2025.R"
16 | utils_file <- "R/30DayChartChallenge2025/utils.R"
17 | config_file <- "R/30DayChartChallenge2025/30DayChartChallenge2025.yml"
18 | font_path_fa <- "fonts/fa-brands-400.ttf"
19 | output_path <- "R/30DayChartChallenge2025/plots/"
20 | data_file <- "R/30DayChartChallenge2025/data/day_1.csv"
21 |
22 | # Verificar archivos
23 | if (!file.exists(themes_file)) stop("Archivo de temas no encontrado.")
24 | if (!file.exists(utils_file)) stop("Archivo de utilidades no encontrado.")
25 | if (!file.exists(config_file)) stop("Archivo de configuración no encontrado.")
26 | if (!file.exists(data_file)) stop("Archivo de datos day_1.csv no encontrado en data/.")
27 |
28 | source(themes_file)
29 | source(utils_file)
30 | config <- read_yaml(config_file)
31 |
32 | # --- 3. Configurar Fuentes ---
33 | setup_fonts(fa_brands_path = font_path_fa) # Verifica ruta a fa-brands!
34 |
35 | # --- 4. Cargar y Preparar Datos ---
36 |
37 | # Leer el CSV descargado del INE
38 | dt <- fread(data_file, sep = ";", dec = ",", na.strings = c('""', ".."), encoding = "Latin-1")
39 |
40 | # Limpiar nombres de columnas
41 | original_names <- names(dt)
42 | new_names <- c("Sexo", "Edad", "Tenencia", "Periodo", "Total")
43 | setnames(dt, old = original_names, new = new_names)
44 |
45 | # Filtrar año 2024 y regímenes relevantes
46 | dt_2024 <- dt[Periodo == 2024 & Tenencia %in% c("Propiedad", "Propiedad con hipoteca", "Propiedad sin hipoteca")]
47 |
48 | # Seleccionar columnas necesarias y pivotar para tener el % por tipo de tenencia
49 | dt_prop <- dt_2024[Tenencia %in% c("Propiedad con hipoteca", "Propiedad sin hipoteca"),
50 | .(Edad, Tenencia, Total)]
51 |
52 | # Calcular el porcentaje de "Alquiler u otros" (100 - % Propiedad Total)
53 | dt_prop_total <- dt_2024[Tenencia == "Propiedad", .(Edad, Total_Propiedad = Total)]
54 | dt_calc <- merge(dt_prop, dt_prop_total, by = "Edad", all = TRUE)
55 | dt_calc[, Pct_Alquiler_Otros := 100 - Total_Propiedad]
56 |
57 | # Combinar y dar formato final para ggplot
58 | dt_plot <- rbindlist(list(
59 | dt_calc[!is.na(Tenencia), .(Edad, Tenencia, Total)],
60 | unique(dt_calc[, .(Edad, Tenencia = "Alquiler u otros", Total = Pct_Alquiler_Otros)])
61 | ))
62 |
63 | # Renombrar grupos de edad (opcional) y ordenar factores
64 | dt_plot[, Generacion := factor(Edad,
65 | levels = c("De 16 a 29 años", "De 30 a 44 años", "De 45 a 64 años", "65 y más años"),
66 | labels = c("16-29 años\n(Gen Z / Mill.)", "30-44 años\n(Mill. / Gen X)", "45-64 años\n(Gen X / Boomer)", "65+ años\n(Boomer / Sil.)"))]
67 |
68 | # Ordenar factor de Tenencia para el gráfico apilado
69 | dt_plot[, Tenencia := factor(Tenencia, levels = c("Alquiler u otros", "Propiedad con hipoteca", "Propiedad sin hipoteca"))]
70 |
71 | # Convertir Total a numérico (si fread no lo hizo ya por el dec=",")
72 | dt_plot[, Total := as.numeric(Total)]
73 |
74 | # --- 5. Crear Gráfico ---
75 |
76 | # Definir textos
77 | source_text_day1 <- "INE: Indicadores de Calidad de Vida (2024)"
78 | plot_title <- "Régimen de Tenencia de Vivienda\npor Edad en España (2024)"
79 | plot_subtitle <- "Fracción de la población en cada grupo de edad\nsegún el tipo de tenencia de su vivienda principal"
80 |
81 | # Generar caption
82 | caption_day1 <- generate_caption(
83 | day = 1,
84 | source_text = source_text_day1,
85 | config = config
86 | )
87 |
88 | # Crear el objeto ggplot
89 | gg_day1 <- ggplot(dt_plot, aes(x = Generacion, y = Total, fill = Tenencia)) +
90 | geom_col(position = "fill") +
91 | # Aplicar paleta personalizada de la semana 1
92 | scale_fill_challenge(palette = "week1", discrete = TRUE, # Usaremos los 3 primeros colores
93 | reverse = TRUE, # Invertir orden de colores
94 | guide = guide_legend(reverse = FALSE)) +
95 | # Formatear eje Y como porcentaje
96 | scale_y_continuous(labels = scales::percent_format(), expand = c(0, 0)) +
97 | # Aplicar tema personalizado (ajusta base_size si es necesario)
98 | theme_week1(base_size = 14) +
99 | # Añadir etiquetas y caption
100 | labs(
101 | title = plot_title,
102 | subtitle = plot_subtitle,
103 | x = "Grupo de Edad (Generación Aproximada)",
104 | y = "Porcentaje de Población",
105 | fill = NULL, # QUitar el título de leyenda
106 | caption = caption_day1
107 | ) +
108 | theme(axis.text.x = element_text(angle = 0, hjust = 0.5, size = rel(0.9))) # Ajustar texto eje x
109 |
110 | # --- 6. Guardar Gráfico ---
111 | output_file <- file.path(output_path, "day_1_fractions_tenencia.png")
112 | ggsave(
113 | filename = output_file,
114 | plot = gg_day1,
115 | width = 1200, height = 1200, units = "px", dpi = 300, bg = "white"
116 | )
117 |
118 | message("Gráfico del Día 1 (Tenencia Vivienda) guardado en: ", normalizePath(output_file, mustWork = FALSE))
119 |
120 | # --- Fin day_1.R ---
--------------------------------------------------------------------------------
/R/30DayChartChallenge2025/category_3_relationships/day_15_complicated/day_15.R:
--------------------------------------------------------------------------------
1 | # --- Day 15: Complicated (Palmer Penguins Traits Matrix) ---
2 | # #30DayChartChallenge 2025
3 | # Autor: Michal Kinel (Datos: palmerpenguins R package)
4 | # Matriz de scatter plots (ggpairs) mostrando relaciones complejas
5 | # entre rasgos de pingüinos, coloreado por especie.
6 |
7 | # --- 1. Cargar Librerías ---
8 | library(ggplot2)
9 | library(data.table)
10 | library(yaml)
11 | library(showtext)
12 | library(ggtext)
13 | library(scales)
14 | library(grid)
15 | library(palmerpenguins)
16 | library(GGally)
17 |
18 | # --- 2. Cargar Configuración, Temas y Utilidades ---
19 | themes_file <- "R/30DayChartChallenge2025/themes_30DCC2025.R"
20 | utils_file <- "R/30DayChartChallenge2025/utils.R"
21 | config_file <- "R/30DayChartChallenge2025/30DayChartChallenge2025.yml"
22 | font_path_fa <- "fonts/fa-brands-400.ttf"
23 | output_path <- "R/30DayChartChallenge2025/plots/"
24 |
25 | # Verificar existencia de archivos y cargar
26 | if (!file.exists(themes_file)) stop("Archivo de temas no encontrado: ", themes_file)
27 | if (!file.exists(utils_file)) stop("Archivo de utilidades no encontrado: ", utils_file)
28 | if (!file.exists(config_file)) stop("Archivo de configuración no encontrado: ", config_file)
29 | source(themes_file)
30 | source(utils_file)
31 | config <- read_yaml(config_file)
32 |
33 | # --- 3. Configurar Fuentes ---
34 | setup_fonts(fa_brands_path = font_path_fa) # Carga "Cabin"
35 |
36 | # --- 4. Cargar y Preparar Datos ---
37 |
38 | message("Cargando datos del paquete palmerpenguins...")
39 | penguins_dt <- as.data.table(penguins)
40 |
41 | # Seleccionar columnas relevantes y eliminar filas con NAs en ellas
42 | cols_for_plot <- c("species", "bill_length_mm", "bill_depth_mm", "flipper_length_mm", "body_mass_g")
43 | penguins_clean_dt <- na.omit(penguins_dt, cols = cols_for_plot)
44 |
45 | # No necesitamos logaritmos aquí, las escalas son razonables
46 | message("Número de pingüinos después de limpiar NAs: ", nrow(penguins_clean_dt))
47 | message("Especies: ", paste(levels(penguins_clean_dt$species), collapse=", "))
48 |
49 | message("Renombrando columnas a Español...")
50 | setnames(penguins_clean_dt,
51 | old = c("bill_length_mm", "bill_depth_mm", "flipper_length_mm", "body_mass_g", "species"),
52 | new = c("Longitud Pico (mm)", "Profundidad Pico (mm)", "Longitud Aleta (mm)", "Masa Corporal (g)", "Especie")
53 | )
54 | print(summary(penguins_clean_dt))
55 |
56 |
57 | # --- 5. Crear Matriz de Scatter Plots (ggpairs) ---
58 |
59 | # Definir textos
60 | source_text_day15 <- "Source: palmerpenguins R package (Gorman, Williams & Fraser, 2014. PLoS ONE)"
61 | plot_title <- "Relaciones Complejas: Pingüinos de Palmer"
62 | plot_subtitle <- "Matriz de relaciones entre medidas corporales por especie.\nInf: Scatterplots, Sup: Correlación (Pearson), Diag: Densidad."
63 |
64 | # Generar caption
65 | caption_day15 <- generate_caption(
66 | day = 15,
67 | source_text = source_text_day15,
68 | config = config,
69 | color_text_source = "#5D4037",
70 | color_text_author = "#6B8E23"
71 | )
72 |
73 |
74 | # Columnas numéricas para incluir en la matriz
75 | ggpairs_cols <- c("Longitud Pico (mm)", "Longitud Aleta (mm)", "Masa Corporal (g)")
76 |
77 | # Colores
78 | bg_col <- "#FAF0E6"
79 | num_species <- length(levels(penguins_clean_dt$Especie))
80 | plot_colors <- challenge_pal("week3_animals")(num_species)
81 | names(plot_colors) <- levels(penguins_clean_dt$species)
82 |
83 | message("Generando gráfico ggpairs...")
84 | # Crear el objeto ggpairs
85 | gg_day15_matrix <- ggpairs(
86 | data = penguins_clean_dt,
87 | columns = ggpairs_cols,
88 | mapping = aes(color = Especie, alpha = 0.7), # Color por especie
89 | upper = list(continuous = wrap("cor", size = 4.5, stars = FALSE)), # Correlación
90 | lower = list(continuous = wrap("points", size = 2.5)), # Scatterplot
91 | diag = list(continuous = wrap("densityDiag", alpha = 0.6)), # Densidad
92 | title = plot_title, # Título principal integrado
93 | progress = FALSE # Ocultar barra de progreso de ggpairs
94 | )
95 |
96 | # Aplicar tema y escalas DESPUÉS de crear el objeto ggpairs
97 | gg_day15 <- gg_day15_matrix +
98 | theme_week3_animals(base_size = 9, base_family = "Cabin") + # Tamaño base reducido para la matriz
99 | scale_color_manual(values = plot_colors, name = "Especie") +
100 | scale_fill_manual(values = plot_colors, name = "Especie") + # Para las densidades
101 | labs(subtitle = plot_subtitle, caption = caption_day15) + # Añadir subtítulo y caption
102 | # Ajustes específicos para ggpairs si son necesarios
103 | theme(
104 | strip.background = element_rect(fill=alpha(bg_col, 0.8), color=NA), # Fondo etiquetas panel semi-transp
105 | strip.text = element_text(face="bold", size=rel(1.5), color="#5D4037"), # Texto etiquetas panel
106 | aspect.ratio = NULL
107 | )
108 |
109 | message("Gráfico ggpairs generado.")
110 |
111 | # --- 6. Guardar Gráfico ---
112 | output_file <- file.path(output_path, "day_15_complicated_penguins.png")
113 | # Darle un poco más de tamaño para que la matriz se vea bien
114 | ggsave(
115 | filename = output_file,
116 | plot = gg_day15,
117 | width = 1200, height = 1200, units = "px", dpi = 150, bg = bg_col
118 | )
119 |
120 | message("Gráfico del Día 15 (Complicated Penguins ggpairs) guardado en: ", normalizePath(output_file, mustWork = FALSE))
121 |
122 | # --- Fin day_15_complicated_penguins.R ---
--------------------------------------------------------------------------------
/R/30DayChartChallenge2025/category_1_comparisons/day_5_ranking/day_5.R:
--------------------------------------------------------------------------------
1 | # --- Day 5: Ranking (Lollipop Chart - Precio Vivienda Distritos Madrid) ---
2 | # #30DayChartChallenge 2025
3 | # Autor: Michal Kinel (Datos: Idealista)
4 |
5 | # --- 1. Cargar Librerías ---
6 | library(data.table)
7 | library(ggplot2)
8 | library(dplyr)
9 | library(yaml)
10 | library(showtext)
11 | library(ggtext)
12 | library(scales) # Para formatear etiquetas
13 |
14 | # --- 2. Cargar Configuración, Temas y Utilidades ---
15 | themes_file <- "R/30DayChartChallenge2025/themes_30DCC2025.R"
16 | utils_file <- "R/30DayChartChallenge2025/utils.R"
17 | config_file <- "R/30DayChartChallenge2025/30DayChartChallenge2025.yml"
18 | font_path_fa <- "fonts/fa-brands-400.ttf"
19 | output_path <- "R/30DayChartChallenge2025/plots/"
20 |
21 | if (!file.exists(utils_file)) stop("Archivo de temas no encontrado.")
22 | if (!file.exists(utils_file)) stop("Archivo de utilidades no encontrado.")
23 | if (!file.exists(config_file)) stop("Archivo de configuración no encontrado.")
24 |
25 | source(themes_file)
26 | source(utils_file)
27 | config <- read_yaml(config_file)
28 |
29 | # --- 3. Configurar Fuentes ---
30 | setup_fonts(fa_brands_path = font_path_fa)
31 |
32 | # --- 4. Preparar Datos ---
33 | distritos <- c("Salamanca", "Chamberí", "Retiro", "Chamartín", "Centro", "Moncloa",
34 | "Arganzuela", "Tetuán", "Hortaleza", "Fuencarral", "Ciudad Lineal",
35 | "Barajas", "Moratalaz", "San Blas", "Latina", "Vicálvaro",
36 | "Carabanchel", "Villa de Vallecas", "Usera", "Puente de Vallecas", "Villaverde")
37 | precios <- c(9374, 7677, 7014, 6988, 6816, 5500, 5341, 5162, 4745, 4572, 4219,
38 | 4070, 3607, 3362, 3275, 3171, 3039, 3032, 2880, 2648, 2294) # Idealista Mar 2025
39 | fuente_datos_real <- "Idealista (Marzo 2025)"
40 |
41 | # Crear el data.table inicial
42 | dt_distritos_ranking <- data.table(
43 | Distrito = factor(distritos),
44 | Precio_m2 = precios
45 | )
46 |
47 | # Precio medio Madrid
48 | precio_medio_madrid <- 5321 # Idealista Mar 2025
49 |
50 | # Calcular diferencia y tipo usando sintaxis data.table (:= para añadir columnas)
51 | dt_distritos_ranking[, Diff_vs_Avg := Precio_m2 - precio_medio_madrid]
52 | dt_distritos_ranking[, Tipo := fifelse(Diff_vs_Avg >= 0, "Superior a la Media", "Inferior a la Media")]
53 | dt_distritos_ranking[, Tipo := factor(Tipo, levels = c("Superior a la Media", "Inferior a la Media"))]
54 |
55 | # --- 5. Crear Gráfico ---
56 |
57 | # Definir textos
58 | plot_title <- "Ranking de Distritos de Madrid"
59 | plot_subtitle <- paste0("Diferencia del precio medio (€/m²) de cada distrito\nrespecto a la media de Madrid (Media Madrid = ",
60 | number(precio_medio_madrid, accuracy=1, big.mark=".", decimal.mark=","), " €/m²)")
61 |
62 | # Generar caption
63 | caption_day5 <- generate_caption(
64 | day = 5,
65 | source_text = fuente_datos_real,
66 | config = config
67 | )
68 |
69 | # Colores para los tipos
70 | colores_tipo <- c("Superior a la Media" = paleta_week1[1], # Azul oscuro
71 | "Inferior a la Media" = paleta_week1[4]) # Rojo oscuro
72 |
73 | # Rango de variación
74 | rango <- dt_distritos_ranking[, round((max(c(max(Diff_vs_Avg), abs(min(Diff_vs_Avg)))) * 1.1) / 500) * 500 ]
75 |
76 | # Crear el gráfico de piruleta divergente horizontal ordenado
77 | gg_day5 <- dt_distritos_ranking[,
78 | ggplot(.SD, aes(x = Diff_vs_Avg, y = reorder(Distrito, Diff_vs_Avg))) +
79 | # Línea vertical en cero (la media)
80 | geom_vline(xintercept = 0, color = paleta_week1[2], linewidth = 1.05) +
81 | # Segmento (palo de la piruleta) desde 0 hasta la diferencia
82 | geom_segment(aes(x = 0, xend = Diff_vs_Avg,
83 | y = reorder(Distrito, Diff_vs_Avg),
84 | yend = reorder(Distrito, Diff_vs_Avg)),
85 | color = fifelse(Tipo == "Superior a la Media", paleta_week1[1], paleta_week1[4]),
86 | linewidth = 1.1) +
87 | # Punto (cabeza de la piruleta), coloreado por Tipo (encima/debajo media)
88 | geom_point(aes(color = Tipo), size = 2.5) +
89 | # Asignar colores manualmente
90 | scale_color_manual(values = colores_tipo, guide = "none") + # Ocultar leyenda de color
91 | # Formatear eje X
92 | scale_x_continuous(
93 | limits = c(-rango, rango),
94 | breaks = seq(-rango, rango, 1500),
95 | expand = c(0.1, 0.1),
96 | labels = label_number(big.mark = ".", decimal.mark = ",", suffix = " €")) +
97 | # Aplicar tema personalizado
98 | theme_week1(base_size = 10) +
99 | # Añadir etiquetas y caption
100 | labs(
101 | title = plot_title,
102 | subtitle = plot_subtitle,
103 | x = "Diferencia vs Precio Medio (€/m²)",
104 | y = NULL,
105 | caption = caption_day5
106 | ) +
107 | # Ajustes adicionales al tema
108 | theme(
109 | panel.grid.major.y = element_blank(), # Sin líneas grid horizontales
110 | panel.grid.minor.x = element_blank(), # Sin grids menores en X
111 | axis.text.y = element_text(size = rel(1)),
112 | plot.margin = margin(15, 30, 10, 15)
113 | )]
114 |
115 | # --- 6. Guardar Gráfico ---
116 | output_file <- file.path(output_path, "day_5_ranking_madrid_diverging_lollipop.png")
117 | ggsave(
118 | filename = output_file,
119 | plot = gg_day5,
120 | width = 1200, height = 1200, units = "px", dpi = 300, bg = "white"
121 | )
122 |
123 | message("Gráfico del Día 5 (Diverging Lollipop Madrid) guardado en: ", normalizePath(output_file, mustWork = FALSE))
124 |
125 | # --- Fin day_5.R ---
--------------------------------------------------------------------------------
/R/2024/week_03/2024_w03_calendar.R:
--------------------------------------------------------------------------------
1 | # Header ------------------------------------------------------------------
2 | #
3 | # Author: Michal Kinel
4 | # Copyright (c) Michal Kinel, 2024
5 | # Email: michal.kinel@gmail.com
6 | #
7 | # Date: 2024-01-21
8 | #
9 | # Script Name:2024_w03_calendar
10 | #
11 | # Script Description: Make a calendar with ggplot2
12 | #
13 | #
14 | # Notes:
15 | #
16 | #
17 |
18 | # Set options -------------------------------------------------------------
19 | cat("Setting options... \n\n", sep = "")
20 | options(scipen = 999) # turns off scientific notation
21 | options(encoding = "UTF-8") # sets string encoding to UTF-8 instead of ANSI
22 |
23 |
24 | # Install packages & load libraries ---------------------------------------
25 | cat("Install packages & load libraries... \n\n", sep = "")
26 | packages <- c("tidyverse", "data.table", "zoo", "extrafont") # list of packages to load
27 | n_packages <- length(packages) # count how many packages are required
28 |
29 | new_pkg <- packages[!(packages %in% installed.packages())] # determine which packages aren't installed
30 |
31 | # Install missing packages
32 | if(length(new_pkg)){
33 | install.packages(new_pkg)
34 | }
35 |
36 | # Load all requried libraries
37 | for(n in 1:n_packages){
38 | cat("Loading Library #", n, " of ", n_packages, "... Currently Loading: ", packages[n], "\n", sep = "")
39 | lib_load <- paste("library(\"",packages[n],"\")", sep = "") # create string of text for loading each library
40 | eval(parse(text = lib_load)) # evaluate the string to load the library
41 | }
42 |
43 |
44 | # Data --------------------------------------------------------------------
45 | cat("Data... \n\n", sep = "")
46 |
47 | # Create data frame
48 | calendar <- data.table(
49 | date = seq.Date(as.Date("2024-01-01"), as.Date("2024-12-31"), by = "day")
50 | )
51 |
52 | # Add month
53 | calendar[, month := str_to_title(lubridate::month(date,
54 | label = TRUE,
55 | abbr = FALSE))]
56 | calendar[, month := factor(month, levels = unique(month))]
57 |
58 | # Add week
59 | calendar[, week := lubridate::week(date)]
60 |
61 | # Add day
62 | calendar[, day := day(date)]
63 |
64 | # Add weekday
65 | calendar[, weekday := {
66 | weekdays(date, abbreviate = TRUE) %>%
67 | fct_inorder()
68 | }]
69 |
70 | # Sunday as first day of week
71 | calendar[, weekend_holydays := fifelse(wday(date) %in% c(7, 1), "weekend", "workdays")]
72 |
73 | # Holydays Spain
74 | holdays <-
75 | c(
76 | "2024-01-01",
77 | "2024-03-29",
78 | "2024-05-01",
79 | "2024-08-15",
80 | "2024-10-12",
81 | "2024-11-01",
82 | "2024-12-06",
83 | "2024-12-25"
84 | ) %>% as.Date()
85 |
86 | # Add holydays
87 | calendar[, weekend_holydays := fifelse(date %in% holdays, "holydays", weekend_holydays)]
88 |
89 | # Add week of month
90 | calendar[, week_month := frank(week, ties.method = "dense"), by = month]
91 |
92 |
93 | # Style -------------------------------------------------------------------
94 | # Color palette
95 | background <- "#fffefa"
96 | weekday_color <- "#313743"
97 | weekend_color <- "#67b7b5"
98 | holiday_color <- "#fa334c"
99 |
100 | # Load fonts
101 | loadfonts(device = "win")
102 |
103 | # Fonts
104 | font_base <- "Lato"
105 | font_title <- "Lato Black"
106 |
107 |
108 | # Plot --------------------------------------------------------------------
109 | cat("Plot... \n\n", sep = "")
110 |
111 | plot <- calendar %>%
112 | ggplot(aes(x = weekday, y = week_month)) +
113 | geom_tile(alpha = 0.8, aes(fill = weekend_holydays)) +
114 | geom_text(
115 | aes(label = day),
116 | family = font_base,
117 | color = fifelse(calendar$weekend_holydays != "weekend", "white", "black"),
118 | size = 3
119 | ) +
120 | facet_wrap( ~ month, scales = "free_x", ncol = 3) +
121 | scale_x_discrete() +
122 | scale_y_reverse(breaks = NULL) +
123 | labs(title = "Calendario 2024",
124 | fill = NULL,
125 | caption = "Festivos de España en rojo\nmichal0091") +
126 | theme_void() +
127 | scale_fill_manual(values = c(holiday_color, weekend_color, weekday_color)) +
128 | # Add theme elements
129 | theme(
130 | plot.margin = margin(1, 0.5, 1, 1, "cm"),
131 | axis.text.x = element_text(
132 | color = weekday_color,
133 | family = font_base,
134 | size = 10,
135 | vjust = 2
136 | ),
137 | # add plot title
138 | plot.title = element_text(
139 | hjust = 0.5,
140 | vjust = 3,
141 | color = weekday_color,
142 | family = font_title,
143 | size = 28
144 | ),
145 | # add plot caption
146 | plot.caption = element_text(
147 | hjust = 1,
148 | color = weekday_color,
149 | family = font_base,
150 | size = 8
151 | ),
152 | # add legend
153 | legend.position = "none",
154 | # add panel spacing
155 | panel.spacing = unit(0.5, "lines"),
156 | # add panel background
157 | panel.background = element_rect(fill = background, color = background),
158 | # add plot background
159 | plot.background = element_rect(fill = background, color = background)
160 | )
161 |
162 |
163 | # Save plot ---------------------------------------------------------------
164 | cat("Saving plot... \n\n", sep = "")
165 |
166 | ggsave(
167 | filename = "calendar_2024.png",
168 | path = normalizePath("R/2024/week_03/"),
169 | plot = plot,
170 | device = "png",
171 | units = "cm",
172 | width = 21,
173 | height = 15.75
174 | )
175 |
--------------------------------------------------------------------------------
/R/30DayChartChallenge2024/day_28/trend_tourist.csv:
--------------------------------------------------------------------------------
1 | Fecha;Extranjeros y España (excluida Canarias)
2 | 03/2024;2018375
3 | 02/2024;1836746
4 | 01/2024;1739341
5 | 2023;19280684
6 | 12/2023;1905982
7 | 11/2023;1726909
8 | 10/2023;1737311
9 | 09/2023;1470212
10 | 08/2023;1576004
11 | 07/2023;1610288
12 | 06/2023;1395483
13 | 05/2023;1385742
14 | 04/2023;1573367
15 | 03/2023;1707195
16 | 02/2023;1596895
17 | 01/2023;1595296
18 | 2022;17286949
19 | 12/2022;1765971
20 | 11/2022;1585099
21 | 10/2022;1633480
22 | 09/2022;1367100
23 | 08/2022;1544046
24 | 07/2022;1555727
25 | 06/2022;1330794
26 | 05/2022;1263332
27 | 04/2022;1496211
28 | 03/2022;1465502
29 | 02/2022;1257258
30 | 01/2022;1022429
31 | 2021;8296043
32 | 12/2021;1297710
33 | 11/2021;1318285
34 | 10/2021;1343200
35 | 09/2021;968990
36 | 08/2021;1026248
37 | 07/2021;809895
38 | 06/2021;466837
39 | 05/2021;328486
40 | 04/2021;216136
41 | 03/2021;207988
42 | 02/2021;145546
43 | 01/2021;166722
44 | 2020;5693229
45 | 2004;12660634
46 | 01/2004;1045261
47 | 02/2004;1090596
48 | 03/2004;1107029
49 | 04/2004;1041639
50 | 05/2004;844375
51 | 06/2004;847026
52 | 07/2004;1103344
53 | 08/2004;1231906
54 | 09/2004;1013299
55 | 10/2004;1163031
56 | 11/2004;1059114
57 | 12/2004;1114014
58 | 2005;12750771
59 | 01/2005;1078251
60 | 02/2005;1047982
61 | 03/2005;1172431
62 | 04/2005;961002
63 | 05/2005;844561
64 | 06/2005;861976
65 | 07/2005;1139866
66 | 08/2005;1230369
67 | 09/2005;1024833
68 | 10/2005;1190416
69 | 11/2005;1087188
70 | 12/2005;1111896
71 | 2006;13155406
72 | 01/2006;1045095
73 | 02/2006;1031214
74 | 03/2006;1182122
75 | 04/2006;1142390
76 | 05/2006;885815
77 | 06/2006;945703
78 | 07/2006;1196527
79 | 08/2006;1248696
80 | 09/2006;1054592
81 | 10/2006;1179535
82 | 11/2006;1084442
83 | 12/2006;1159275
84 | 2007;13219349
85 | 01/2007;1027616
86 | 02/2007;1060870
87 | 03/2007;1232057
88 | 04/2007;1062158
89 | 05/2007;859800
90 | 06/2007;938926
91 | 07/2007;1187133
92 | 08/2007;1249286
93 | 09/2007;1056387
94 | 10/2007;1185806
95 | 11/2007;1149307
96 | 12/2007;1210003
97 | 2008;13072068
98 | 01/2008;1076417
99 | 02/2008;1155648
100 | 03/2008;1318717
101 | 04/2008;1024491
102 | 05/2008;907577
103 | 06/2008;967121
104 | 07/2008;1155030
105 | 08/2008;1246988
106 | 09/2008;966991
107 | 10/2008;1086215
108 | 11/2008;1090470
109 | 12/2008;1076403
110 | 2009;11468333
111 | 01/2009;980784
112 | 02/2009;954506
113 | 03/2009;1028973
114 | 04/2009;953968
115 | 05/2009;750573
116 | 06/2009;783223
117 | 07/2009;999853
118 | 08/2009;1072655
119 | 09/2009;841073
120 | 10/2009;1010268
121 | 11/2009;1027625
122 | 12/2009;1064832
123 | 2010;12177546
124 | 01/2010;1013938
125 | 02/2010;997684
126 | 03/2010;1117882
127 | 04/2010;840838
128 | 05/2010;826209
129 | 06/2010;887440
130 | 07/2010;1100600
131 | 08/2010;1140848
132 | 09/2010;940526
133 | 10/2010;1142974
134 | 11/2010;1083642
135 | 12/2010;1084965
136 | 2011;13877848
137 | 01/2011;1107701
138 | 02/2011;1162507
139 | 03/2011;1287837
140 | 04/2011;1231543
141 | 05/2011;897630
142 | 06/2011;973818
143 | 07/2011;1230204
144 | 08/2011;1238784
145 | 09/2011;1069499
146 | 10/2011;1267519
147 | 11/2011;1173475
148 | 12/2011;1237331
149 | 2012;13230571
150 | 01/2012;1143053
151 | 02/2012;1134348
152 | 03/2012;1235969
153 | 04/2012;1044372
154 | 05/2012;881032
155 | 06/2012;965951
156 | 07/2012;1174376
157 | 08/2012;1158847
158 | 09/2012;1027775
159 | 10/2012;1179455
160 | 11/2012;1101961
161 | 12/2012;1183432
162 | 2013;13526439
163 | 01/2013;1075738
164 | 02/2013;1075968
165 | 03/2013;1261886
166 | 04/2013;998282
167 | 05/2013;913159
168 | 06/2013;967756
169 | 07/2013;1157622
170 | 08/2013;1184428
171 | 09/2013;1042595
172 | 10/2013;1245588
173 | 11/2013;1286597
174 | 12/2013;1316820
175 | 2014;14478580
176 | 01/2014;1195148
177 | 02/2014;1172309
178 | 03/2014;1327581
179 | 04/2014;1209557
180 | 05/2014;989555
181 | 06/2014;1045130
182 | 07/2014;1252328
183 | 08/2014;1301767
184 | 09/2014;1105163
185 | 10/2014;1309887
186 | 11/2014;1258780
187 | 12/2014;1311375
188 | 2015;14933111
189 | 01/2015;1232987
190 | 02/2015;1204708
191 | 03/2015;1332001
192 | 04/2015;1150904
193 | 05/2015;1045917
194 | 06/2015;1060467
195 | 07/2015;1280137
196 | 08/2015;1347280
197 | 09/2015;1141670
198 | 10/2015;1394716
199 | 11/2015;1338754
200 | 12/2015;1403570
201 | 2016;17014118
202 | 01/2016;1361098
203 | 02/2016;1375027
204 | 03/2016;1510160
205 | 04/2016;1312287
206 | 05/2016;1207896
207 | 06/2016;1256106
208 | 07/2016;1516606
209 | 08/2016;1514672
210 | 09/2016;1321137
211 | 10/2016;1587147
212 | 11/2016;1452652
213 | 12/2016;1599330
214 | 2017;18180995
215 | 01/2017;1452746
216 | 02/2017;1438342
217 | 03/2017;1568698
218 | 04/2017;1572978
219 | 05/2017;1296939
220 | 06/2017;1378762
221 | 07/2017;1602888
222 | 08/2017;1574087
223 | 09/2017;1446259
224 | 10/2017;1655159
225 | 11/2017;1540900
226 | 12/2017;1653237
227 | 2018;18059717
228 | 01/2018;1492573
229 | 02/2018;1470660
230 | 03/2018;1676389
231 | 04/2018;1409198
232 | 05/2018;1293551
233 | 06/2018;1354855
234 | 07/2018;1560690
235 | 08/2018;1544335
236 | 09/2018;1434169
237 | 10/2018;1638278
238 | 11/2018;1522264
239 | 12/2018;1662755
240 | 2019;17737398
241 | 01/2019;1491569
242 | 02/2019;1476107
243 | 03/2019;1674785
244 | 04/2019;1471735
245 | 05/2019;1258250
246 | 06/2019;1357063
247 | 07/2019;1495809
248 | 08/2019;1498147
249 | 09/2019;1356218
250 | 10/2019;1519793
251 | 11/2019;1516957
252 | 12/2019;1620965
253 | 01/2020;1433358
254 | 02/2020;1460630
255 | 03/2020;598185
256 | 04/2020;4327
257 | 05/2020;9394
258 | 06/2020;35163
259 | 07/2020;428525
260 | 08/2020;530971
261 | 09/2020;286234
262 | 10/2020;300365
263 | 11/2020;251888
264 | 12/2020;354189
265 |
--------------------------------------------------------------------------------
/R/30DayChartChallenge2025/utils.R:
--------------------------------------------------------------------------------
1 | # --- utils.R ---
2 |
3 | library(glue)
4 | library(ggtext)
5 | library(sysfonts)
6 | library(showtext)
7 | library(ggplot2)
8 |
9 | font_add(family = "fa-brands", regular = "fonts/fa-brands-400.ttf")
10 | font_add(family = "fa-solid", regular = "fonts/fa-solid-900.ttf")
11 |
12 | showtext_auto()
13 |
14 | #' Genera el texto del pie de foto (caption) para los gráficos del #30DayChartChallenge
15 | #'
16 | #' Utiliza la información del archivo de configuración YAML y los detalles específicos del día.
17 | #' Requiere que ggtext esté instalado y una fuente de iconos (ej. Font Awesome) configurada con showtext.
18 | #'
19 | #' @param day El número del día (1-30).
20 | #' @param source_text El texto que describe la fuente de los datos para ese día.
21 | #' @param config El objeto de configuración cargado desde el archivo YAML.
22 | #' @param color_text_author Color para el autor y hashtags principales (predeterminado: azul).
23 | #' @param color_text_source Color para la fuente y nombres de usuario (predeterminado: negro/gris).
24 | #' @param icon_font_family Nombre de la familia de la fuente de iconos (predeterminado: 'Font Awesome 6 Brands').
25 | #'
26 | #' @return Una cadena de texto formateada en HTML/Markdown lista para usar con ggtext::element_markdown().
27 | #'
28 | generate_caption <- function(day,
29 | source_text,
30 | config,
31 | color_text_author = "#286e8c", # Azul de tu paleta semana 1
32 | color_text_source = "#373737", # Gris oscuro de tu paleta semana 1
33 | icon_font_family = "fa-brands") { # Asegúrate de que este nombre coincide con cómo lo carga showtext
34 |
35 | # Extraer información por defecto del config
36 | defaults <- config$defaults
37 | author <- defaults$author_name
38 | social_media <- defaults$social_media
39 | main_hashtag <- defaults$main_hashtag
40 |
41 | # Extraer información del día específico del config
42 | daily_info <- config$daily_prompts[[day]]
43 | if (is.null(daily_info)) {
44 | stop(paste("No se encontró información para el día", day, "en el archivo de configuración."))
45 | }
46 | theme_name <- daily_info$theme
47 | day_hashtag <- paste0("#Day", day) # Hashtag #DayN
48 |
49 | # Construir la parte de redes sociales dinámicamente
50 | social_html_parts <- character()
51 | build_social_part <- function(icon_code_html, username) {
52 | glue(" {icon_code_html}; {username} ")
53 | }
54 |
55 | build_mastodon_part <- function(icon_code_html, username, server) {
56 | glue("{icon_code_html}; {username}@{server} ")
57 | }
58 |
59 | if (!is.null(social_media$github_username) && !is.null(social_media$github_icon)) {
60 | social_html_parts <- c(social_html_parts, build_social_part(social_media$github_icon, social_media$github_username))
61 | }
62 |
63 | if (!is.null(social_media$linkedin_username) && !is.null(social_media$linkedin_icon)) {
64 | social_html_parts <- c(social_html_parts, build_social_part(social_media$linkedin_icon, social_media$linkedin_username))
65 | }
66 |
67 | if (!is.null(social_media$mastodon_username) && !is.null(social_media$mastodon_icon) && !is.null(social_media$mastodon_server)) {
68 | social_html_parts <- c(social_html_parts, build_mastodon_part(social_media$mastodon_icon, social_media$mastodon_username, social_media$mastodon_server))
69 | }
70 |
71 |
72 | # Separador entre redes sociales: varios espacios sin ruptura
73 | social_string <- paste(social_html_parts, collapse = " ")
74 |
75 |
76 | # Construir el caption final usando glue
77 | caption <- glue::glue(
78 | "Viz: {author} | ",
79 | " Source: {source_text}
",
80 | "{social_string}
",
81 | "{main_hashtag} | {day_hashtag}: {theme_name}"
82 | )
83 |
84 | return(caption)
85 | }
86 |
87 | # --- Función para Configurar Fuentes ---
88 |
89 | #' Carga las fuentes necesarias para el #30DayChartChallenge usando showtext
90 | #'
91 | #' Carga Roboto, Baumans desde Google Fonts y Font Awesome Brands desde un archivo local.
92 | #' Activa showtext para su uso en gráficos.
93 | #'
94 | #' @param fa_brands_path
95 | #'
96 | setup_fonts <- function(fa_brands_path = "fonts/fa-brands-400.ttf") {
97 |
98 | # Cargar fuentes de Google Fonts
99 | font_add_google("Roboto", "Roboto")
100 | font_add_google("Roboto", "Roboto bold", regular.wt = 700)
101 | font_add_google("Baumans", "Baumans")
102 | font_add_google("Roboto Mono", "Roboto Mono")
103 | font_add_google("Exo 2", "Exo 2")
104 | font_add_google("Cabin", "Cabin")
105 | font_add_google("Lato", "Lato") # El País?
106 | font_add_google("Gudea", "Gudea") # NatGeo
107 |
108 | # Cargar fuente de iconos local (Font Awesome Brands)
109 | if (file.exists(fa_brands_path)) {
110 | font_add(family = "fa-brands", regular = fa_brands_path)
111 | } else {
112 | warning(paste("Archivo de fuente Font Awesome Brands no encontrado en:",
113 | normalizePath(fa_brands_path, mustWork = FALSE),
114 | "\nLos iconos no se mostrarán correctamente."))
115 | }
116 |
117 | # Activar showtext para que ggplot use estas fuentes
118 | showtext_auto()
119 | }
120 |
--------------------------------------------------------------------------------
/R/30DayChartChallenge2025/category_4_timeseries/day_19_smooth/day_19.R:
--------------------------------------------------------------------------------
1 | # --- Day 19: Smooth (Polish Presidential Polls Trends) ---
2 | # #30DayChartChallenge 2025
3 | # Autor: Michal Kinel (Datos: User CSV - Polish Election Polls 2025)
4 | # Evolución suavizada de la intención de voto para candidatos presidenciales
5 | # en Polonia, incluyendo orientación política.
6 |
7 | # --- 1. Cargar Librerías ---
8 | library(ggplot2)
9 | library(data.table)
10 | library(yaml)
11 | library(showtext)
12 | library(ggtext)
13 | library(scales)
14 | library(lubridate)
15 | library(viridis)
16 |
17 | # --- 2. Cargar Configuración, Temas y Utilidades ---
18 | themes_file <- "R/30DayChartChallenge2025/themes_30DCC2025.R"
19 | utils_file <- "R/30DayChartChallenge2025/utils.R"
20 | config_file <- "R/30DayChartChallenge2025/30DayChartChallenge2025.yml"
21 | font_path_fa <- "fonts/fa-brands-400.ttf"
22 | output_path <- "R/30DayChartChallenge2025/plots/"
23 |
24 | # Verificar existencia de archivos y cargar
25 | source(themes_file) # Carga paletas y theme_week4_social
26 | source(utils_file) # Carga caption y setup_fonts (con "Lato")
27 | config <- read_yaml(config_file)
28 |
29 | # --- 3. Configurar Fuentes ---
30 | setup_fonts(fa_brands_path = font_path_fa)
31 |
32 | # --- 4. Cargar y Preparar Datos de Encuestas Polonia ---
33 |
34 | data_file <- "R/30DayChartChallenge2025/data/elecciones_polonia_2025.csv"
35 | if (!file.exists(data_file)) stop("Archivo CSV de encuestas no encontrado: ", data_file)
36 |
37 | message("Cargando datos desde: ", data_file)
38 | # Leer CSV especificando separador y decimal
39 | polls_dt <- data.table::fread(data_file, sep = ";", dec = ",", header = TRUE)
40 | message("Datos cargados. ", nrow(polls_dt), " filas iniciales.")
41 | print(head(polls_dt))
42 |
43 | # --- Limpieza y Preparación ---
44 |
45 | # Convertir fecha y apoyo
46 | polls_dt[, fecha := lubridate::as_date(fecha)]
47 | polls_dt[, apoyo_pct := as.numeric(apoyo) * 100]
48 |
49 | # Limpiar nombres y orientación (quitar espacios extra)
50 | cols_to_trim <- c("candidato", "partido", "orientación")
51 | polls_dt[, (cols_to_trim) := lapply(.SD, trimws), .SDcols = cols_to_trim]
52 |
53 | # Crear etiqueta combinada para leyenda
54 | polls_dt[, label_legend := paste0(candidato, " (", orientación, ")")]
55 |
56 |
57 | # Filtrar NAs generados y rango de fechas si es necesario
58 | cols_check_na <- c("fecha", "apoyo_pct", "label_legend")
59 | polls_clean_dt <- na.omit(polls_dt, cols = cols_check_na)
60 |
61 | # Seleccionar 6 candidatos con más apoyo medio
62 | top_6_candidatos <- polls_clean_dt[, .(apoyo_medio = mean(apoyo_pct, na.rm = TRUE)), label_legend][order(-apoyo_medio), head(label_legend, 6)]
63 | polls_clean_dt <- polls_clean_dt[label_legend %in% top_6_candidatos]
64 |
65 | # Convertir a factor para ordenar leyenda
66 | polls_clean_dt[, label_legend := factor(label_legend, levels = top_6_candidatos)]
67 |
68 | message("Datos limpios y preparados: ", nrow(polls_clean_dt), " registros válidos.")
69 | message("Rango de fechas: ", min(polls_clean_dt$fecha), " a ", max(polls_clean_dt$fecha))
70 | message("Candidatos (Orientación) encontrados: ", paste(levels(polls_clean_dt$label_legend), collapse=", "))
71 |
72 | # --- 5. Crear Gráfico de Tendencias Suavizadas ---
73 |
74 | # Definir textos
75 | source_text_day19 <- "Fuente: Diversas encuestadoras (elaboración propia)"
76 | plot_title <- "Evolución Intención de Voto: Presidenciales Polonia 2025"
77 | plot_subtitle <- paste0("Tendencias suavizadas (LOESS/GAM) basadas en encuestas publicadas.\nPeriodo: ",
78 | format(min(polls_clean_dt$fecha), "%b %Y"), " - ", format(max(polls_clean_dt$fecha), "%b %Y"))
79 |
80 | # Generar caption
81 | caption_day19 <- generate_caption(
82 | day = 19,
83 | source_text = source_text_day19,
84 | config = config,
85 | color_text_source = "#5c5c5c",
86 | color_text_author = "#757de8"
87 | )
88 |
89 | # Colores y tema
90 | bg_col <- "#F2F2F2"
91 | text_col <- challenge_palettes$week4_social['grey']
92 | num_candidatos <- length(levels(polls_clean_dt$label_legend))
93 |
94 | # Crear el gráfico
95 | gg_day19 <- ggplot(polls_clean_dt, aes(x = fecha, y = apoyo_pct, color = label_legend, group = label_legend)) +
96 |
97 | # Opcional: Puntos de encuestas individuales (muy transparentes)
98 | geom_point(alpha = 0.3, size = 2, shape = 19, show.legend = FALSE) +
99 |
100 | # Líneas suavizadas (método por defecto LOESS/GAM)
101 | geom_smooth(se = FALSE, linewidth = 1.2, span = 0.95) +
102 |
103 | # Escala de color
104 | scale_color_manual(values = challenge_pal("week4_social")(num_candidatos), name = NULL) +
105 |
106 | # Formato de ejes
107 | scale_y_continuous(labels = scales::label_percent(scale = 1), limits = c(0, 40), expand = expansion(mult=c(0, 0.05))) +
108 | scale_x_date(date_breaks = "1 month", date_labels = "%B %Y") + # Ajusta breaks según rango real
109 |
110 | # Aplicar tema
111 | theme_week4_social(base_family = "Lato", base_size = 11) + # Usar tema semana 4
112 |
113 | # Leyenda
114 | guides(color = guide_legend(override.aes = list(alpha = 1, linewidth=2), ncol = 3)) + # Leyenda más clara y en 2 cols si es larga
115 |
116 | # Etiquetas y caption
117 | labs(
118 | title = plot_title,
119 | subtitle = plot_subtitle,
120 | x = "Fecha de Encuesta",
121 | y = "Apoyo Estimado (%)",
122 | caption = caption_day19
123 | ) +
124 | theme(legend.title.align = 0.5) # Centrar título leyenda
125 |
126 | # --- 6. Guardar Gráfico ---
127 | output_file <- file.path(output_path, "day_19_smooth_polls_poland.png")
128 | ggsave(
129 | filename = output_file,
130 | plot = gg_day19,
131 | width = 1200, height = 1200, units = "px", dpi = 150, bg = bg_col
132 | )
133 |
134 | message("Gráfico del Día 19 (Smooth Polls) guardado en: ", normalizePath(output_file, mustWork = FALSE))
135 |
136 | # --- Fin day_19_smooth_polls.R ---
--------------------------------------------------------------------------------
/R/30DayChartChallenge2025/category_4_timeseries/day_23_logscale/day_23.R:
--------------------------------------------------------------------------------
1 | # --- Day 23: Log Scale (Long-Term GDP per Capita Growth in Spain) ---
2 | # #30DayChartChallenge 2025
3 | # Autor: Michal Kinel (Datos: World Bank via WDI package)
4 | # Evolución del PIB per cápita de España (PPA, const.) en escala logarítmica.
5 |
6 | # --- 1. Cargar Librerías ---
7 | library(ggplot2)
8 | library(data.table)
9 | library(yaml)
10 | library(showtext)
11 | library(ggtext)
12 | library(scales)
13 | library(lubridate)
14 | library(WDI)
15 |
16 | # --- 2. Cargar Configuración, Temas y Utilidades ---
17 | themes_file <- "R/30DayChartChallenge2025/themes_30DCC2025.R"
18 | utils_file <- "R/30DayChartChallenge2025/utils.R"
19 | config_file <- "R/30DayChartChallenge2025/30DayChartChallenge2025.yml"
20 | font_path_fa <- "fonts/fa-brands-400.ttf"
21 | output_path <- "R/30DayChartChallenge2025/plots/"
22 |
23 | # Verificar existencia de archivos y cargar
24 | source(themes_file) # Carga paletas y theme_week4_social
25 | source(utils_file) # Carga caption y setup_fonts (con "Lato")
26 | config <- read_yaml(config_file)
27 |
28 | # --- 3. Configurar Fuentes ---
29 | setup_fonts(fa_brands_path = font_path_fa) # Carga "Lato"
30 |
31 | # --- 4. Cargar y Preparar Datos del Banco Mundial ---
32 |
33 | # Indicador: PIB per capita, PPA (dólares internacionales constantes de 2017)
34 | indicator_code <- "NY.GDP.PCAP.PP.KD"
35 | country_code <- "ES" # Código ISO para España
36 | start_year <- 1990 # Datos disponibles desde 1990 en este indicador
37 | # Obtener hasta el último año completo con datos (normalmente con 1-2 años de retraso)
38 | end_year <- year(Sys.Date()) - 2
39 |
40 | message("Descargando datos del PIB per cápita para España desde World Bank (WDI)...")
41 | gdp_raw_df <- tryCatch({
42 | WDI(country = country_code, indicator = indicator_code, start = start_year, end = end_year, extra = FALSE)
43 | }, error = function(e) {
44 | warning("Error al descargar datos de WDI. Comprueba la conexión o el indicador.\nError: ", e$message)
45 | return(NULL)
46 | })
47 |
48 | if (is.null(gdp_raw_df) || nrow(gdp_raw_df) == 0) {
49 | stop("No se pudieron obtener datos del Banco Mundial.")
50 | }
51 |
52 | # Convertir a data.table y limpiar
53 | gdp_dt <- as.data.table(gdp_raw_df)
54 | setnames(gdp_dt, indicator_code, "GDP_pc_ppp_kd", skip_absent=TRUE)
55 | if (!"GDP_pc_ppp_kd" %in% names(gdp_dt)) {
56 | # Intentar encontrarla si WDI usó un nombre ligeramente diferente
57 | potential_name <- names(gdp_dt)[!names(gdp_dt) %in% c("iso2c", "country", "year", "iso3c")]
58 | if (length(potential_name) == 1) {
59 | message("Columna indicador encontrada como: ", potential_name)
60 | setnames(gdp_dt, potential_name, "GDP_pc_ppp_kd")
61 | } else {
62 | stop("No se pudo identificar la columna del indicador GDP descargada.")
63 | }
64 | }
65 | gdp_dt <- gdp_dt[, .(Year = year, GDP_pc = GDP_pc_ppp_kd)] # Seleccionar y renombrar
66 | gdp_dt <- na.omit(gdp_dt) # Quitar años con NA
67 | setorder(gdp_dt, Year) # Ordenar por año
68 |
69 | message("Datos de PIB per cápita preparados. Rango: ", min(gdp_dt$Year), "-", max(gdp_dt$Year))
70 | print(tail(gdp_dt))
71 | print(summary(gdp_dt))
72 |
73 | # --- Definir períodos de crisis ---
74 | crisis_periods <- data.frame(
75 | start_year = c(1992, 2008, 2020),
76 | end_year = c(1994, 2013, 2021)
77 | )
78 |
79 | # --- 5. Crear Gráfico de Líneas con Escala Logarítmica ---
80 |
81 | # Definir textos
82 | source_text_day23 <- "Fuente: World Bank (Indicator: NY.GDP.PCAP.PP.KD) via WDI package"
83 | plot_title <- paste0("Crecimiento Económico de España (", min(gdp_dt$Year), "-", max(gdp_dt$Year),")")
84 | plot_subtitle <- paste0("Evolución del PIB per cápita (PPA, dólares const. 2017).\n",
85 | "La escala logarítmica del eje Y revela cambios en la tasa de crecimiento.\n",
86 | "Las áreas sombreadas indican períodos de crisis económicas en España.")
87 | # Generar caption
88 | caption_day23 <- generate_caption(
89 | day = 23,
90 | source_text = source_text_day23,
91 | config = config,
92 | color_text_source = "#5c5c5c",
93 | color_text_author = "#757de8"
94 | )
95 |
96 | # Colores y tema
97 | bg_col <- "#F2F2F2"
98 | line_color <- challenge_palettes$week4_social['indigo'] # Azul índigo
99 |
100 | # Crear el gráfico
101 | gg_day23 <- ggplot(gdp_dt, aes(x = Year, y = GDP_pc)) +
102 | geom_line(color = line_color, linewidth = 1.2, alpha = 0.8) +
103 | geom_point(color = line_color, size = 2, shape=21, fill=bg_col, stroke=0.5) +
104 |
105 | # Añadir sombreado para periodos de crisis
106 | geom_rect(
107 | data = crisis_periods,
108 | mapping = aes(xmin = start_year, xmax = end_year, ymin = 0, ymax = Inf),
109 | fill = challenge_palettes$week4_social['pink'] , alpha = 0.2,
110 | inherit.aes = FALSE
111 | ) +
112 |
113 | scale_y_log10(
114 | name = "PIB per Cápita (PPA, $ const. 2017) [Escala Log]", # Título eje Y
115 | labels = scales::label_dollar(accuracy = 1), # Formato Dólar (simplificado)
116 | breaks = scales::log_breaks(n = 6) # Ajustar número de breaks si es necesario
117 | ) +
118 |
119 | # Escala X (Año)
120 | scale_x_continuous(n.breaks = 8) +
121 |
122 | # Aplicar tema
123 | theme_week4_social(base_family = "Lato", base_size = 10) +
124 |
125 | # Etiquetas y caption
126 | labs(
127 | title = plot_title,
128 | subtitle = plot_subtitle,
129 | x = "Año",
130 | caption = caption_day23
131 | ) +
132 | theme(legend.position = "none")
133 |
134 |
135 |
136 |
137 |
138 | # --- 6. Guardar Gráfico ---
139 | output_file <- file.path(output_path, "day_23_logscale_gdp_spain.png")
140 | ggsave(
141 | filename = output_file,
142 | plot = gg_day23,
143 | width = 1200, height = 1200, units = "px", dpi = 150, bg = bg_col # Apaisado
144 | )
145 |
146 | message("Gráfico del Día 23 (Log Scale GDP) guardado en: ", normalizePath(output_file, mustWork = FALSE))
147 |
148 | # --- Fin day_23_logscale_gdp.R ---
--------------------------------------------------------------------------------
/R/30DayChartChallenge2025/category_2_distributions/day_11_stripes/day_11.R:
--------------------------------------------------------------------------------
1 | # --- Day 11: Stripes (High Volatility VIX Days Barcode) ---
2 | # #30DayChartChallenge 2025
3 | # Autor: Michal Kinel (Datos: Yahoo Finance)
4 | # Visualización de días con alta volatilidad (VIX > umbral) como "rayas"
5 | # en una línea de tiempo, creando un efecto de código de barras.
6 |
7 | # --- 1. Cargar Librerías ---
8 | library(quantmod)
9 | library(ggplot2)
10 | library(data.table)
11 | library(lubridate)
12 | library(yaml)
13 | library(showtext)
14 | library(ggtext)
15 | library(scales)
16 |
17 | # --- 2. Cargar Configuración, Temas y Utilidades ---
18 | themes_file <- "R/30DayChartChallenge2025/themes_30DCC2025.R"
19 | utils_file <- "R/30DayChartChallenge2025/utils.R"
20 | config_file <- "R/30DayChartChallenge2025/30DayChartChallenge2025.yml"
21 | font_path_fa <- "fonts/fa-brands-400.ttf"
22 | output_path <- "R/30DayChartChallenge2025/plots/"
23 |
24 | # Verificar existencia de archivos
25 | if (!file.exists(themes_file)) stop("Archivo de temas no encontrado: ", themes_file)
26 | if (!file.exists(utils_file)) stop("Archivo de utilidades no encontrado: ", utils_file)
27 | if (!file.exists(config_file)) stop("Archivo de configuración no encontrado: ", config_file)
28 |
29 | source(themes_file) # Carga paletas y temas
30 | source(utils_file) # Carga caption y setup_fonts
31 | config <- read_yaml(config_file)
32 |
33 | # --- 3. Configurar Fuentes ---
34 | setup_fonts(fa_brands_path = font_path_fa)
35 |
36 | # --- 4. Obtener y Preparar Datos VIX ---
37 |
38 | # Definir fechas y ticker
39 | end_date <- Sys.Date()
40 | start_date <- as.Date("1993-01-20") # Ampliar para cubrir más presidentes (desde Clinton)
41 | ticker_symbol <- "^VIX"
42 | ticker_name <- "VIX Index"
43 |
44 | message("Descargando datos para ", ticker_name, " (", ticker_symbol, ")")
45 | data_xts <- tryCatch({
46 | getSymbols(
47 | ticker_symbol,
48 | src = "yahoo",
49 | from = start_date,
50 | to = end_date,
51 | auto.assign = FALSE
52 | )
53 | }, error = function(e) {
54 | warning("Error al descargar ", ticker_symbol, ": ", e$message)
55 | return(NULL)
56 | })
57 |
58 |
59 | if (!is.null(data_xts)) {
60 | price_col_name <- paste0(gsub("\\^", "", ticker_symbol), ".Close")
61 | if (!price_col_name %in% names(data_xts)) {
62 | price_col_name <- grep("\\.Close", names(data_xts), value = TRUE)[1]
63 | if(is.na(price_col_name)) stop("No se encontró la columna de cierre para VIX.")
64 | warning("Usando columna de cierre detectada: ", price_col_name)
65 | }
66 | vix_levels_xts <- data_xts[, price_col_name]
67 | names(vix_levels_xts) <- "VIX_Level"
68 |
69 | vix_dt <- data.table(
70 | Date = index(vix_levels_xts),
71 | VIX_Level = as.numeric(coredata(vix_levels_xts))
72 | )
73 | vix_dt <- na.omit(vix_dt)
74 | message("Procesado ", ticker_name, ". ", nrow(vix_dt), " niveles diarios obtenidos.")
75 |
76 | # --- Filtrar días de alta volatilidad ---
77 | high_vol_thr <- 30 # Umbral para considerar alta volatilidad (puedes usar 35 si prefieres)
78 | vix_high_days_dt <- vix_dt[VIX_Level >= high_vol_thr]
79 | message(nrow(vix_high_days_dt), " días encontrados con VIX >= ", high_vol_thr)
80 |
81 | } else {
82 | stop("No se pudieron obtener datos para ", ticker_name, " (", ticker_symbol, ").")
83 | }
84 |
85 | # Verificar datos filtrados
86 | print(head(vix_high_days_dt))
87 |
88 |
89 | # --- 5. Crear Gráfico de Código de Barras ("Stripes") ---
90 |
91 | # Definir textos
92 | source_text_day11 <- paste0("Yahoo Finance (^VIX). Periodo: ",
93 | format(start_date, "%Y-%m-%d"), " a ",
94 | format(end_date, "%Y-%m-%d"))
95 | plot_title <- paste0("Días de Alta Volatilidad del Mercado (VIX >= ", high_vol_thr, ")")
96 | plot_subtitle <- "Cada 'raya' vertical representa un día donde el Índice VIX cerró por encima del umbral,\nmostrando clústeres de estrés en el mercado a lo largo del tiempo."
97 |
98 | # Generar caption
99 | caption_day11 <- generate_caption(
100 | day = 11,
101 | source_text = source_text_day11,
102 | config = config,
103 | color_text_source = "#E8EAED",
104 | color_text_author = "#4FC3F7"
105 | )
106 |
107 | # Colores y tema
108 | stripe_color <- paleta_week2_tech[5]
109 | text_col <- "#E8EAED"
110 | bg_col <- "#202124"
111 |
112 | # Crear el gráfico
113 | gg_day11 <- ggplot(vix_high_days_dt, aes(x = Date)) +
114 | # Usar geom_segment para crear las rayas verticales
115 | geom_segment(aes(y = 0, yend = 1), # Fija la altura de las rayas
116 | color = stripe_color,
117 | linewidth = 0.4) + # Ajusta el grosor de las rayas
118 |
119 | # Escala de fecha
120 | scale_x_date(date_breaks = "2 years", date_labels = "%Y", expand = expansion(mult = 0.01)) +
121 |
122 | # Aplicar tema personalizado
123 | theme_week2_tech(base_size = 11) +
124 |
125 | # Ocultar el eje Y ya que no tiene significado aquí
126 | theme(
127 | axis.text.y = element_blank(),
128 | axis.ticks.y = element_blank(),
129 | axis.title.y = element_blank(),
130 | panel.grid.major.y = element_blank(),
131 | panel.grid.minor.y = element_blank()
132 | ) +
133 |
134 | # Añadir etiquetas y caption
135 | labs(
136 | title = plot_title,
137 | subtitle = plot_subtitle,
138 | x = "Año",
139 | y = NULL, # Eje Y sin título
140 | caption = caption_day11
141 | ) +
142 | # Fijar límites Y (opcional pero ayuda a asegurar que los segmentos llenen el espacio)
143 | coord_cartesian(ylim = c(0, 1))
144 |
145 |
146 | # --- 6. Guardar Gráfico ---
147 | output_file <- file.path(output_path, "day_11_stripes_vix_barcode.png")
148 | ggsave(
149 | filename = output_file,
150 | plot = gg_day11,
151 | width = 1200, height = 1200, units = "px", dpi = 150, bg = bg_col # Más ancho y menos alto
152 | )
153 |
154 | message("Gráfico del Día 11 (VIX Barcode Stripes) guardado en: ", normalizePath(output_file, mustWork = FALSE))
155 |
156 | # --- Fin day_11_stripes_vix_barcode.R ---
--------------------------------------------------------------------------------
/R/30DayChartChallenge2025/30DayChartChallenge2025.yml:
--------------------------------------------------------------------------------
1 | # -----------------------------------------------------
2 | # Archivo de Configuración para #30DayChartChallenge 2025
3 | # -----------------------------------------------------
4 |
5 | # Información por defecto/global
6 | defaults:
7 | author_name: "Michal Kinel"
8 | social_media:
9 | github_icon: ""
10 | github_username: "michal0091"
11 | mastodon_icon: ""
12 | mastodon_username: "miki_peltzer"
13 | mastodon_server: "techhub.social"
14 | linkedin_icon: ""
15 | linkedin_username: "michal-kinel"
16 | main_hashtag: "#30DayChartChallenge"
17 | year: 2025
18 |
19 | # Prompts diarios (Abril 2025)
20 | daily_prompts:
21 | 1:
22 | day: 1
23 | category: "Comparisons"
24 | theme: "Fractions"
25 | hashtag: "#Day1"
26 | data_source_url: null
27 | notes: ""
28 | 2:
29 | day: 2
30 | category: "Comparisons"
31 | theme: "Slope"
32 | hashtag: "#Day2"
33 | data_source_url: null
34 | notes: ""
35 | 3:
36 | day: 3
37 | category: "Comparisons"
38 | theme: "Circular"
39 | hashtag: "#Day3"
40 | data_source_url: null
41 | notes: ""
42 | 4:
43 | day: 4
44 | category: "Comparisons"
45 | theme: "Big or Small"
46 | hashtag: "#Day4"
47 | data_source_url: null
48 | notes: ""
49 | 5:
50 | day: 5
51 | category: "Comparisons"
52 | theme: "Ranking"
53 | hashtag: "#Day5"
54 | data_source_url: null
55 | notes: ""
56 | 6:
57 | day: 6
58 | category: "Comparisons"
59 | theme: "Florence Nightingale"
60 | hashtag: "#Day6"
61 | data_source_url: null
62 | notes: "Theme day"
63 | 7:
64 | day: 7
65 | category: "Distributions"
66 | theme: "Outliers"
67 | hashtag: "#Day7"
68 | data_source_url: null
69 | notes: ""
70 | 8:
71 | day: 8
72 | category: "Distributions"
73 | theme: "Histogram"
74 | hashtag: "#Day8"
75 | data_source_url: null
76 | notes: ""
77 | 9:
78 | day: 9
79 | category: "Distributions"
80 | theme: "Diverging"
81 | hashtag: "#Day9"
82 | data_source_url: null
83 | notes: ""
84 | 10:
85 | day: 10
86 | category: "Distributions"
87 | theme: "Multi-modal"
88 | hashtag: "#Day10"
89 | data_source_url: null
90 | notes: ""
91 | 11:
92 | day: 11
93 | category: "Distributions"
94 | theme: "Stripes"
95 | hashtag: "#Day11"
96 | data_source_url: null
97 | notes: ""
98 | 12:
99 | day: 12
100 | category: "Distributions"
101 | theme: "Data.gov"
102 | hashtag: "#Day12"
103 | data_source_url: "https://www.data.gov/" # Portal principal
104 | notes: "Data day"
105 | 13:
106 | day: 13
107 | category: "Relationships"
108 | theme: "Clusters"
109 | hashtag: "#Day13"
110 | data_source_url: null
111 | notes: ""
112 | 14:
113 | day: 14
114 | category: "Relationships"
115 | theme: "Kinship"
116 | hashtag: "#Day14"
117 | data_source_url: null
118 | notes: ""
119 | 15:
120 | day: 15
121 | category: "Relationships"
122 | theme: "Complicated"
123 | hashtag: "#Day15"
124 | data_source_url: null
125 | notes: ""
126 | 16:
127 | day: 16
128 | category: "Relationships"
129 | theme: "Negative"
130 | hashtag: "#Day16"
131 | data_source_url: null
132 | notes: ""
133 | 17:
134 | day: 17
135 | category: "Relationships"
136 | theme: "Birds"
137 | hashtag: "#Day17"
138 | data_source_url: null # Posibles fuentes: eBird, GBIF
139 | notes: ""
140 | 18:
141 | day: 18
142 | category: "Relationships"
143 | theme: "El País"
144 | hashtag: "#Day18"
145 | data_source_url: null # Buscar datos en El País o relacionados
146 | notes: "Theme day"
147 | 19:
148 | day: 19
149 | category: "Time Series"
150 | theme: "Smooth"
151 | hashtag: "#Day19"
152 | data_source_url: null
153 | notes: ""
154 | 20:
155 | day: 20
156 | category: "Time Series"
157 | theme: "Urbanization"
158 | hashtag: "#Day20"
159 | data_source_url: null # Posibles fuentes: ONU, Banco Mundial, INE
160 | notes: ""
161 | 21:
162 | day: 21
163 | category: "Time Series"
164 | theme: "Fossils"
165 | hashtag: "#Day21"
166 | data_source_url: null
167 | notes: ""
168 | 22:
169 | day: 22
170 | category: "Time Series"
171 | theme: "Stars"
172 | hashtag: "#Day22"
173 | data_source_url: null # Posibles fuentes: NASA, ESA
174 | notes: ""
175 | 23:
176 | day: 23
177 | category: "Time Series"
178 | theme: "Log Scale"
179 | hashtag: "#Day23"
180 | data_source_url: null
181 | notes: ""
182 | 24:
183 | day: 24
184 | category: "Time Series"
185 | theme: "World Health Organization"
186 | hashtag: "#Day24"
187 | data_source_url: "https://www.who.int/data/gho" # Portal de datos GHO de la OMS
188 | notes: "Data day"
189 | 25:
190 | day: 25
191 | category: "Uncertainties"
192 | theme: "Risk"
193 | hashtag: "#Day25"
194 | data_source_url: null
195 | notes: ""
196 | 26:
197 | day: 26
198 | category: "Uncertainties"
199 | theme: "Monochrome"
200 | hashtag: "#Day26"
201 | data_source_url: null
202 | notes: ""
203 | 27:
204 | day: 27
205 | category: "Uncertainties"
206 | theme: "Noise"
207 | hashtag: "#Day27"
208 | data_source_url: null
209 | notes: ""
210 | 28:
211 | day: 28
212 | category: "Uncertainties"
213 | theme: "Inclusion"
214 | hashtag: "#Day28"
215 | data_source_url: null
216 | notes: ""
217 | 29:
218 | day: 29
219 | category: "Uncertainties"
220 | theme: "Extraterrestrial"
221 | hashtag: "#Day29"
222 | data_source_url: null
223 | notes: ""
224 | 30:
225 | day: 30
226 | category: "Uncertainties"
227 | theme: "National Geographic"
228 | hashtag: "#Day30"
229 | data_source_url: null # Buscar datos o inspiración en NatGeo
230 | notes: "Theme day"
231 |
--------------------------------------------------------------------------------
/R/2024/week_12/2024_w12_portfolio.R:
--------------------------------------------------------------------------------
1 | # Header ------------------------------------------------------------------
2 | #
3 | # Author: Michal Kinel
4 | # Copyright (c) Michal Kinel, 2024
5 | # Email: michal.kinel@gmail.com
6 | #
7 | # Date: 2024-03-24
8 | #
9 | # Script Name: 2024_w12_portfolio.R
10 | #
11 | # Script Description: Protfolio allocation plot
12 | #
13 | #
14 | # Notes:
15 | #
16 | #
17 |
18 | # Set options -------------------------------------------------------------
19 | cat("Setting options... \n\n", sep = "")
20 | options(scipen = 999) # turns off scientific notation
21 | options(encoding = "UTF-8") # sets string encoding to UTF-8 instead of ANSI
22 |
23 |
24 | # Install packages & load libraries ---------------------------------------
25 | cat("Install packages & load libraries... \n\n", sep = "")
26 | packages <- c("tidyverse", "data.table", "zoo", "showtext", "sysfonts", "treemapify",
27 | "patchwork") # list of packages to load
28 | n_packages <- length(packages) # count how many packages are required
29 |
30 | new_pkg <- packages[!(packages %in% installed.packages())] # determine which packages aren't installed
31 |
32 | # Install missing packages
33 | if(length(new_pkg)){
34 | install.packages(new_pkg)
35 | }
36 |
37 | # Load all requried libraries
38 | for(n in 1:n_packages){
39 | cat("Loading Library #", n, " of ", n_packages, "... Currently Loading: ", packages[n], "\n", sep = "")
40 | lib_load <- paste("library(\"",packages[n],"\")", sep = "") # create string of text for loading each library
41 | eval(parse(text = lib_load)) # evaluate the string to load the library
42 | }
43 |
44 | # Load data ---------------------------------------------------------------
45 | cat("Load data... \n\n", sep = "")
46 | portfolio <- fread("R/2024/week_12/portfolio.csv")
47 | portfolio[, prp := as.numeric(gsub(",", ".", prp))]
48 |
49 | # Styles ------------------------------------------------------------------
50 | cat("Setting style... \n\n", sep = "")
51 | source("R/2024/theme.R")
52 |
53 |
54 | # Plot --------------------------------------------------------------------
55 | cat("Plot... \n\n", sep = "")
56 |
57 | pais <- portfolio[type == "pais"][order(-prp)][, .(prp = sum(prp)), by = .(name = fifelse(
58 | prp > 1, name, paste0("Otros ", length(name), " países")
59 | ))]
60 | pais[, name := factor(name, levels = pais$name)]
61 |
62 | # Pais plot
63 | pais_plot <- pais %>%
64 | ggplot(aes(area = prp, label = paste0(name, " ", sprintf("%2.0f", prp), "% "))) +
65 | geom_treemap(fill = color_set_1, color = color_background, layout = "scol") +
66 | geom_treemap_text(family = "inter_regular",
67 | colour = color_background,
68 | place = "centre",
69 | grow = TRUE,
70 | layout = "scol",
71 | min.size = 7) +
72 | labs(subtitle = "Porcentaje de la cartera en cada país") +
73 | theme_my()
74 |
75 |
76 | # Sector
77 | sector <-
78 | portfolio[type == "sector"][order(-prp)][, .(prp = sum(prp)), by = .(name = fifelse(prp > 2.5, name, paste0("Otros sectores")))]
79 | sector[, name := factor(name, levels = sector$name)]
80 |
81 | # Sector base plot
82 | sector_base_plot <-
83 | sector %>%
84 | ggplot(aes(prp, name)) +
85 | geom_col() +
86 | facet_wrap(~ name, ncol = 1, scales = "free_y") +
87 | scale_x_continuous(name = "Porcentaje",
88 | expand = c(0, 0),
89 | limits = c(0, 35)) +
90 | scale_y_discrete(guide = "none") +
91 | theme_my() +
92 | theme(
93 | strip.background = element_rect(fill = color_background, color = color_background),
94 | strip.text = element_text(
95 | color = color_text_2,
96 | family = "inter_regular",
97 | hjust = 0,
98 | margin = margin(1, 1, 1, 1),
99 | size = rel(1.1),
100 | face = "bold"
101 | ),
102 | panel.grid.major = element_blank()
103 | )
104 |
105 | # Sector plot add text labels
106 | sector_plot <- sector_base_plot +
107 | geom_text(
108 | aes(
109 | label = paste0(" ", sprintf("%2.1f", prp), "% "),
110 | color = prp > 5,
111 | hjust = prp > 5
112 | ),
113 | size = 4,
114 | fontface = "bold",
115 | family = "inter_regular"
116 | ) +
117 | scale_color_manual(values = c(color_text_1, color_background),
118 | guide = "none") +
119 | labs(subtitle = "Porcentaje de la cartera en cada sector", y = NULL)
120 |
121 |
122 | # Combine plots -----------------------------------------------------------
123 | cat("Combine plots... \n\n", sep = "")
124 | combined_plot <-
125 | pais_plot + sector_plot +
126 | plot_layout(widths = c(1, 1)) +
127 | plot_annotation(
128 | title = "Distribución de la cartera de ETFs",
129 | caption = caption_text(source_text = "Own elaboration"),
130 | theme = theme_my()
131 | )
132 |
133 |
134 | # Save plot ---------------------------------------------------------------
135 | cat("Save plot... \n\n", sep = "")
136 |
137 | ggsave(
138 | filename = "portfolio_distr_plot.png",
139 | path = normalizePath("R/2024/week_12"),
140 | plot = combined_plot,
141 | device = "png",
142 | units = "mm",
143 | width = 105*2,
144 | height = 105,
145 | dpi = 320
146 | )
147 |
148 | # Save separately
149 | pais_plot_solo <- pais_plot +
150 | labs(
151 | title = "Distribución de la cartera de ETFs",
152 | caption = caption_text(source_text = "Elaboración propia"))
153 | ggsave(
154 | filename = "portfolio_distr_pais_plot.png",
155 | path = normalizePath("R/2024/week_12"),
156 | plot = pais_plot_solo,
157 | device = "png",
158 | units = "mm",
159 | width = 105,
160 | height = 105,
161 | dpi = 320
162 | )
163 |
164 |
165 | pais_sector_solo <- sector_plot +
166 | labs(
167 | title = "Distribución de la cartera de ETFs",
168 | caption = caption_text(source_text = "Elaboración propia"))
169 | ggsave(
170 | filename = "portfolio_distr_sector_plot.png",
171 | path = normalizePath("R/2024/week_12"),
172 | plot = pais_sector_solo,
173 | device = "png",
174 | units = "mm",
175 | width = 105,
176 | height = 105,
177 | dpi = 320
178 | )
179 |
180 |
181 |
--------------------------------------------------------------------------------
/R/30DayChartChallenge2025/category_3_relationships/day_18_el_pais/day_18.R:
--------------------------------------------------------------------------------
1 | # --- Day 18: El País (Theme Day) - Housing Effort vs Pet Ratio (Madrid) ---
2 | # #30DayChartChallenge 2025
3 | # Autor: Michal Kinel (Datos: datos.madrid.es / INE - via User CSV)
4 | # Relación entre esfuerzo inmobiliario y ratio mascotas/niño por distrito y año.
5 | # Estilo inspirado en El País.
6 |
7 | # --- 1. Cargar Librerías ---
8 | library(ggplot2)
9 | library(data.table)
10 | library(yaml)
11 | library(showtext)
12 | library(ggtext)
13 | library(scales)
14 | library(lubridate)
15 | library(viridis) # Para escala de color de año
16 |
17 | # --- 2. Cargar Configuración, Temas y Utilidades ---
18 | themes_file <- "R/30DayChartChallenge2025/themes_30DCC2025.R"
19 | utils_file <- "R/30DayChartChallenge2025/utils.R"
20 | config_file <- "R/30DayChartChallenge2025/30DayChartChallenge2025.yml"
21 | font_path_fa <- "fonts/fa-brands-400.ttf"
22 | output_path <- "R/30DayChartChallenge2025/plots/"
23 |
24 | # Verificar existencia de archivos y cargar
25 | source(themes_file) # Carga paletas y TEMA EL PAIS
26 | source(utils_file) # Carga caption y setup_fonts (con "Lato")
27 | config <- read_yaml(config_file)
28 |
29 | # --- 3. Configurar Fuentes ---
30 | setup_fonts(fa_brands_path = font_path_fa)
31 |
32 | # --- 4. Cargar y Preparar Datos de Madrid ---
33 | data_dir <- "R/30DayChartChallenge2025/data"
34 | csv_file <- file.path(data_dir, "madrid.csv") # <- Nombre del archivo CSV
35 |
36 | if (!file.exists(csv_file)) stop("Archivo CSV de Madrid no encontrado: ", csv_file)
37 |
38 | message("Cargando datos desde: ", csv_file)
39 | # Leer CSV, ¡cuidado con separador decimal y de miles si no es punto!
40 | # Asumiré punto decimal por defecto. Si es coma, usa dec=",".
41 | madrid_dt <- data.table::fread(csv_file, header = TRUE)
42 | message("Datos cargados. ", nrow(madrid_dt), " filas iniciales.")
43 | print(head(madrid_dt, 2)) # Ver las primeras filas y nombres
44 |
45 | # --- Limpieza y Cálculo de Variables ---
46 | # Limpiar nombres de distrito
47 | madrid_dt[, Distrito := sub("^[0-9]+\\. ", "", Distrito)]
48 |
49 | # Asegurar tipos numéricos (puede necesitar gsub(",",".",...) si decimal es coma)
50 | cols_num <- c("Renta neta media por persona", "Menores de 16",
51 | "ESPECIE CANINA", "ESPECIE FELINA", "precio €/m2 vivienda venta")
52 | madrid_dt[, (cols_num) := lapply(.SD, as.numeric), .SDcols = cols_num]
53 |
54 | # Calcular variables necesarias
55 | madrid_dt[, Total_Pets := `ESPECIE CANINA` + `ESPECIE FELINA`]
56 | # Calcular Ratio (evitando división por cero)
57 | madrid_dt[, Pet_Ratio := fifelse(`Menores de 16` > 0, Total_Pets / `Menores de 16`, NA_real_)]
58 | # Calcular Ingreso Hogar (Asunción: 2x ingreso per cápita ANUAL)
59 | madrid_dt[, Household_Income := `Renta neta media por persona` * 2]
60 | # Calcular Precio Vivienda 75m2
61 | madrid_dt[, Price_75m2 := `precio €/m2 vivienda venta` * 75]
62 | # Calcular Años de Esfuerzo
63 | madrid_dt[, Years_Effort := fifelse(Household_Income > 0, Price_75m2 / Household_Income, NA_real_)]
64 |
65 | # Seleccionar datos finales y quitar NAs
66 | madrid_clean_dt <- na.omit(madrid_dt, cols=c("Distrito", "year", "Pet_Ratio", "Years_Effort", "Household_Income"))
67 |
68 | madrid_clean_dt[, year_f := factor(year)]
69 |
70 | message("Datos calculados y limpios: ", nrow(madrid_clean_dt), " observaciones Distrito-Año.")
71 | print(summary(madrid_clean_dt[, .(Pet_Ratio, Years_Effort)]))
72 | print("Años incluidos:")
73 | print(levels(madrid_clean_dt$year_f))
74 |
75 | # --- 5. Crear Scatter Plot (Estilo El País) ---
76 |
77 | # Definir textos
78 | source_text_day18 <- "Fuente: Portal de Datos Abiertos Ayto. Madrid / INE (elaboración propia)"
79 | plot_title <- "¿El Ladrillo ahoga a la Cigüeña? Mascotas y Esfuerzo Inmobiliario"
80 | plot_subtitle <- "Relación positiva en distritos de Madrid (2015-2022): A más años para pagar el piso, ¿más 'perrhijos' por niño?"
81 |
82 | # Generar caption
83 | caption_day18 <- generate_caption(
84 | day = 18,
85 | source_text = source_text_day18,
86 | config = config,
87 | color_text_source = challenge_palettes$el_pais['text2'],
88 | color_text_author = challenge_palettes$el_pais['text']
89 | )
90 |
91 | # Colores
92 | bg_col <- challenge_palettes$el_pais['bg']
93 | text_col <- challenge_palettes$el_pais['text']
94 | accent_color <- challenge_palettes$el_pais['accent1'] # Azul para regresión
95 |
96 | # Crear el gráfico
97 | gg_day18 <- ggplot(madrid_clean_dt, aes(x = Pet_Ratio, y = Years_Effort)) +
98 | # Puntos coloreados por año
99 | geom_point(aes(color = year_f), alpha = 1, size = 3.5) +
100 |
101 | # Línea de regresión lineal
102 | geom_smooth(method = "lm", color = accent_color, fill = accent_color, alpha = 0.1, se = TRUE, linewidth = 0.8) +
103 |
104 | # Escala de color para año (Viridis es buena opción)
105 | scale_color_manual(values = c(
106 | "#2c85b1", "#96bbd7", "#41373f", "#c6c08c",
107 | "#df3a4d", "#ef9ca6", "#3d5a0e", "#7ab41d"),
108 | name = "Año") + # colores más de El País
109 |
110 | # Guías para leyenda (ajustar ncol si es necesario para 8 años)
111 | guides(color = guide_legend(override.aes = list(size = 4, alpha=1), ncol = 4)) +
112 |
113 |
114 | # Formato de ejes
115 | scale_x_continuous(expand = expansion(mult=c(0.02, 0.05))) + # Empezar eje X en 0
116 | scale_y_continuous(expand = expansion(mult=c(0.02, 0.05))) + # Empezar eje Y en 0
117 |
118 | # Aplicar tema El País
119 | theme_el_pais(base_family = "Lato", base_size = 10) + # Usar Lato, ajustar tamaño base
120 |
121 | # Etiquetas y caption
122 | labs(
123 | title = plot_title,
124 | subtitle = plot_subtitle,
125 | x = "Ratio Mascotas (Perros+Gatos) / Menores 16",
126 | y = "Años de Renta Familiar (Vivienda 75m²)",
127 | caption = caption_day18
128 | ) +
129 | facet_wrap(Distrito ~ ., ncol = 4, scales = "free")
130 |
131 |
132 | # --- 6. Guardar Gráfico ---
133 | output_file <- file.path(output_path, "day_18_el_pais_pets_effort.png")
134 | ggsave(
135 | filename = output_file,
136 | plot = gg_day18,
137 | width = 1400, height = 1400, units = "px", dpi = 150, bg = bg_col
138 | )
139 |
140 | message("Gráfico del Día 18 (El Pais - Pets vs Effort) guardado en: ", normalizePath(output_file, mustWork = FALSE))
141 |
142 | # --- Fin day_18_el_pais.R ---
--------------------------------------------------------------------------------
/R/30DayChartChallenge2025/category_5_uncertainties/day_28_inclusion/day_28.R:
--------------------------------------------------------------------------------
1 | # --- Day 28: Inclusion (Unemployment Rate Disparity & Uncertainty by Spanish Region) ---
2 | # #30DayChartChallenge 2025
3 | # Autor: Michal Kinel (Datos: INE - Encuesta de Población Activa)
4 | # Tasa de paro estimada por CCAA incluyendo Intervalo de Confianza del 95%
5 | # para visualizar disparidad territorial e incertidumbre de la estimación.
6 |
7 | # --- 1. Cargar Librerías ---
8 | library(ggplot2)
9 | library(data.table)
10 | library(yaml)
11 | library(showtext)
12 | library(ggtext)
13 | library(scales)
14 | library(lubridate)
15 |
16 | # --- 2. Cargar Configuración, Temas y Utilidades ---
17 | themes_file <- "R/30DayChartChallenge2025/themes_30DCC2025.R"
18 | utils_file <- "R/30DayChartChallenge2025/utils.R"
19 | config_file <- "R/30DayChartChallenge2025/30DayChartChallenge2025.yml"
20 | font_path_fa <- "fonts/fa-brands-400.ttf"
21 | output_path <- "R/30DayChartChallenge2025/plots/"
22 |
23 | # Verificar existencia de archivos y cargar
24 | source(themes_file) # Carga paletas y theme_week5_uncertainty
25 | source(utils_file)
26 | config <- read_yaml(config_file)
27 |
28 | # --- 3. Configurar Fuentes ---
29 | setup_fonts(fa_brands_path = font_path_fa) # Carga "Lato"
30 |
31 | # --- 4. Cargar y Preparar Datos EPA por CCAA ---
32 |
33 | data_file <- "R/30DayChartChallenge2025/data/epa_paro_ccaa.csv"
34 |
35 | if (!file.exists(data_file)) {
36 | stop("Archivo CSV de EPA por CCAA no encontrado en: ", data_file,
37 | "\nDescárgalo desde INE.es o busca la publicación adecuada.")
38 | }
39 |
40 | message("Cargando datos EPA desde: ", data_file)
41 | epa_dt <- data.table::fread(data_file, encoding = "Latin-1") # Ajusta sep, dec, skip si es necesario
42 | message("Datos EPA cargados. ", nrow(epa_dt), " filas iniciales.")
43 | print(head(epa_dt))
44 | print(names(epa_dt))
45 |
46 |
47 | # --- Limpieza y Preparación ---
48 | setnames(epa_dt,
49 | old = c("Edad", "Sexo", "Comunidades y Ciudades Autónomas", "Periodo", "Total"),
50 | new = c("Edad_Grp", "Sexo_Grp", "CCAA_Raw", "Periodo_Str", "Tasa_Paro"),
51 | skip_absent=TRUE)
52 |
53 | # Filtrar datos necesarios
54 | epa_clean_dt <- epa_dt[Edad_Grp == "Total" & Sexo_Grp == "Ambos sexos"]
55 |
56 | # Limpiar nombre CCAA (quitar código inicial)
57 | epa_clean_dt[, CCAA := trimws(sub("^[0-9]{2} ", "", CCAA_Raw))]
58 |
59 | # Convertir Periodo a Fecha (inicio del trimestre)
60 | epa_clean_dt[, Date := as.Date(zoo::as.yearqtr(Periodo_Str, format = "%YT%q"))]
61 |
62 | # Asegurar que Tasa_Paro es numérica (ya debería serlo si dec="," funcionó)
63 | epa_clean_dt[, Tasa_Paro := as.numeric(Tasa_Paro)]
64 |
65 | # Seleccionar columnas finales y quitar NAs
66 | epa_clean_dt <- epa_clean_dt[!is.na(Date) & !is.na(Tasa_Paro) & !is.na(CCAA),
67 | .(CCAA, Date, Rate = Tasa_Paro)]
68 |
69 | # Corregir algunos nombres de CCAA
70 | epa_clean_dt[, CCAA := fcase(
71 | CCAA == "Madrid, Comunidad de", "Madrid",
72 | CCAA == "Murcia, Región de", "Murcia",
73 | CCAA == "Navarra, Comunidad Foral de", "Navarra",
74 | CCAA == "Rioja, La", "La Rioja",
75 | CCAA == "Asturias, Principado de", "Asturias",
76 | CCAA == "Balears, Illes", "Balears",
77 | CCAA == "Total Nacional", "España",
78 | default = CCAA
79 | )]
80 |
81 | # --- Seleccionar CCAA para visualizar ---
82 | ccaa_seleccionadas <- c(
83 | "Andalucía", "Navarra", "Madrid", "País Vasco", "Castilla y León", "España"
84 | )
85 | epa_plot_dt <- epa_clean_dt[CCAA %in% ccaa_seleccionadas]
86 | # Convertir a factor para leyenda consistente
87 | epa_plot_dt[, CCAA := factor(CCAA, levels = intersect(ccaa_seleccionadas, unique(CCAA)))]
88 |
89 |
90 | message("Datos EPA listos para graficar para: ", paste(levels(epa_plot_dt$CCAA), collapse=", "))
91 | print(tail(epa_plot_dt))
92 |
93 | # --- 5. Crear Gráfico de Líneas Comparativo ---
94 |
95 | # Definir textos
96 | epa_periodo_plot <- paste(min(year(epa_plot_dt$Date)), "-", max(year(epa_plot_dt$Date)))
97 | source_text_day28 <- paste0("Fuente: INE - Encuesta de Población Activa (EPA). Periodo: ", epa_periodo_plot)
98 | plot_title <- "Evolución de la Disparidad Territorial en el Paro (España)"
99 | plot_subtitle <- paste0("Tasa de paro trimestral estimada por CC.AA. seleccionadas.")
100 |
101 | # Generar caption
102 | caption_day28 <- generate_caption(
103 | day = 28,
104 | source_text = source_text_day28,
105 | config = config,
106 | color_text_source = "#000000",
107 | color_text_author = "#455A64"
108 | )
109 |
110 | # Colores y tema
111 | bg_col <- "#FFFFFF"
112 | num_ccaa <- length(levels(epa_plot_dt$CCAA))
113 | # Usar paleta week4_social o week5_uncertainty
114 | plot_colors <- challenge_pal("week4_social")(num_ccaa) # O "week5_uncertainty"
115 | names(plot_colors) <- levels(epa_plot_dt$CCAA)
116 |
117 | # Cambiar color para España
118 | plot_colors["España"] <- "#DE1D1A"
119 |
120 | # Line width
121 | l_width <- rep(1.1, num_ccaa)
122 | names(l_width) <- levels(epa_plot_dt$CCAA)
123 | l_width["España"] <- 1.4
124 |
125 | # Crear el gráfico de líneas
126 | gg_day28 <- ggplot(epa_plot_dt, aes(x = Date, y = Rate, color = CCAA, linewidth = CCAA, group = CCAA)) +
127 | geom_line(alpha = 0.85) +
128 |
129 | # Escala de colores manual
130 | scale_color_manual(values = plot_colors, name = NULL) +
131 | scale_linewidth_manual(values = l_width, name = NULL) +
132 |
133 | # Formato de ejes
134 | scale_y_continuous(labels = scales::label_percent(scale = 1),
135 | name = "Tasa de Paro Estimada (%)") +
136 | scale_x_date(date_breaks = "3 years", date_labels = "%Y",
137 | expand = expansion(mult=c(0.01, 0.01))) +
138 |
139 | # Aplicar tema Semana 5
140 | theme_week5_uncertainty(base_family = "Lato", base_size = 10) +
141 |
142 | # Leyenda
143 | guides(color = guide_legend(nrow = 1)) + # Ajustar columnas
144 |
145 | # Etiquetas y caption
146 | labs(
147 | title = plot_title,
148 | subtitle = plot_subtitle,
149 | x = "Año",
150 | caption = caption_day28
151 | ) +
152 | theme(legend.title = element_blank()) # Confirmar leyenda sin título
153 |
154 | # --- 6. Guardar Gráfico ---
155 | output_file <- file.path(output_path, "day_28_inclusion_epa_ts.png")
156 | ggsave(
157 | filename = output_file,
158 | plot = gg_day28,
159 | width = 1200, height = 1200, units = "px", dpi = 150, bg = bg_col
160 | )
161 |
162 | message("Gráfico del Día 28 (Inclusion EPA TS) guardado en: ", normalizePath(output_file, mustWork = FALSE))
163 |
164 | # --- Fin day_28_inclusion_epa_ts.R ---
--------------------------------------------------------------------------------
/R/30DayChartChallenge2025/category_4_timeseries/day_24_who/day_24.R:
--------------------------------------------------------------------------------
1 | # --- Day 24: WHO (data day) - DTP3 Vaccination Coverage in Spain ---
2 | # #30DayChartChallenge 2025
3 | # Autor: Michal Kinel (Datos: WHO Global Health Observatory)
4 | # Evolución de la cobertura de vacunación con DTP3 en niños de 1 año por grupo de ingresos del Banco Mundial.
5 |
6 | # --- 1. Cargar Librerías ---
7 | library(ggplot2)
8 | library(data.table)
9 | library(yaml)
10 | library(showtext)
11 | library(ggtext)
12 | library(scales)
13 | library(lubridate)
14 |
15 | # --- 2. Cargar Configuración, Temas y Utilidades ---
16 | themes_file <- "R/30DayChartChallenge2025/themes_30DCC2025.R"
17 | utils_file <- "R/30DayChartChallenge2025/utils.R"
18 | config_file <- "R/30DayChartChallenge2025/30DayChartChallenge2025.yml"
19 | font_path_fa <- "fonts/fa-brands-400.ttf"
20 | output_path <- "R/30DayChartChallenge2025/plots/"
21 |
22 | # Verificar existencia de archivos y cargar
23 | source(themes_file)
24 | source(utils_file)
25 | config <- read_yaml(config_file)
26 |
27 |
28 | # --- 3. Configurar Fuentes ---
29 | setup_fonts(fa_brands_path = font_path_fa) # Carga "Lato"
30 |
31 | # --- 4. Cargar y Preparar Datos de Cobertura Vacunal OMS ---
32 |
33 | data_url <- "https://srhdpeuwpubsa.blob.core.windows.net/whdh/DATADOT/INDICATOR/F8E084C_ALL_LATEST.csv"
34 |
35 | message("Cargando datos de cobertura vacunal desde: ", data_url)
36 | vacc_dt <- data.table::fread(data_url)
37 |
38 | if (nrow(vacc_dt) == 0) {
39 | stop("Problema en la lectura de los datos, revisa la URL.")
40 | }
41 | message("Datos cargados. ", nrow(vacc_dt), " filas iniciales.")
42 |
43 |
44 | # --- Limpieza y Preparación ---
45 | col_geo_name <- "GEO_NAME_SHORT"
46 | col_geo_type <- "DIM_GEO_CODE_TYPE"
47 | col_year <- "DIM_TIME"
48 | col_coverage <- "RATE_PER_100_N"
49 |
50 | # Verificar que las columnas existen
51 | required_cols <- c(col_geo_name, col_geo_type, col_year, col_coverage)
52 | if (!all(required_cols %in% names(vacc_dt))) {
53 | stop("El archivo CSV de WHO no contiene las columnas esperadas ('", col_year, "', '", col_coverage,"'). Revisa nombres.")
54 | }
55 |
56 | # Seleccionar, renombrar y asegurar tipos
57 | vacc_clean_dt <- vacc_dt[, .(
58 | Country = as.character(get(col_geo_name)),
59 | Geo_Type = as.character(get(col_geo_type)),
60 | Year = as.numeric(get(col_year)),
61 | Coverage_Pct = as.numeric(get(col_coverage)) # Ya debería ser % (0-100)
62 | )]
63 |
64 | # Filtrar NAs y ordenar
65 | vacc_clean_dt <- na.omit(vacc_clean_dt)
66 | setorder(vacc_clean_dt, Geo_Type, Country, Year)
67 |
68 | # Subset zona de interés
69 | selected_geo_type <- "WORLDBANKINCOMEGROUP"
70 | vacc_clean_dt <- vacc_clean_dt[Geo_Type == selected_geo_type]
71 |
72 | # Traducir grupos de ingresos
73 | vacc_clean_dt[, Income_Group := fcase(
74 | Country == "Low-income economies", "Bajo",
75 | Country == "Lower-middle-income economies", "Medio-Bajo",
76 | Country == "Upper-middle-income economies", "Medio-Alto",
77 | Country == "High-income economies", "Alto"
78 | )]
79 |
80 | # Income_Group como factor ordenado
81 | vacc_clean_dt[, Income_Group := factor(Income_Group, levels = c("Bajo", "Medio-Bajo", "Medio-Alto", "Alto"))]
82 |
83 | message("Datos de vacunación preparados. Rango: ", min(vacc_clean_dt$Year), "-", max(vacc_clean_dt$Year))
84 | print(tail(vacc_clean_dt))
85 | print(summary(vacc_clean_dt))
86 |
87 | # --- 5. Crear Gráfico de Líneas (Cobertura Vacunal) ---
88 |
89 | # Definir textos
90 | source_text_day24 <- "Fuente: WHO/UNICEF Estimates (via WHO Global Health Observatory)"
91 | plot_title <- "Cobertura Vacunal con DTP3 por grupo de ingresos del Banco Mundial"
92 | plot_subtitle <- paste0("Porcentaje estimado de niños/as de 1 año vacunados con 3 dosis de DTP.\nPeriodo: ",
93 | min(vacc_clean_dt$Year), "-", max(vacc_clean_dt$Year), ". Línea objetivo: 95%.")
94 |
95 | # Generar caption
96 | caption_day24 <- generate_caption(
97 | day = 24,
98 | source_text = source_text_day24,
99 | config = config,
100 | color_text_source = "#5c5c5c",
101 | color_text_author = "#757de8"
102 | )
103 |
104 | # Colores y tema
105 | bg_col <- "#F2F2F2"
106 | num_groups <- length(levels(vacc_clean_dt$Income_Group))
107 | color_map_income_group <- setNames(
108 | challenge_pal("week4_social")(num_groups), # Usa tu paleta social
109 | levels(vacc_clean_dt$Income_Group) # Asigna a los niveles del factor
110 | )
111 | target_color <- challenge_palettes$week4_social['pink'] # Rosa para línea objetivo
112 |
113 | # Crear el gráfico de línea
114 | gg_day24 <- ggplot(vacc_clean_dt, aes(x = Year, y = Coverage_Pct, color = Income_Group, group = Income_Group)) +
115 |
116 | # Línea objetivo (ej. 95%)
117 | geom_hline(yintercept = 95, linetype = "dashed", color = target_color, linewidth = 1, alpha=0.8) +
118 | annotate("text", x = min(vacc_clean_dt$Year), y = 96, label = "Objetivo 95%",
119 | hjust = 0, vjust = 0, size = 4.5, color = target_color, family="Lato", fontface="italic") +
120 |
121 | # Línea de cobertura
122 | geom_line(linewidth = 1.3, alpha = 0.9) +
123 | geom_point(size = 2, shape=21, fill=bg_col, stroke=0.6) +
124 |
125 | # Escala de colores manual
126 | scale_color_manual(values = color_map_income_group, name = "Grupo de Ingresos") +
127 |
128 | # Formato de ejes
129 | scale_y_continuous(limits = c(0, 100), # Eje Y de 0 a 100%
130 | labels = scales::label_percent(scale = 1),
131 | expand = expansion(mult=c(0, 0.05)),
132 | name = "Cobertura Estimada (%)") +
133 | scale_x_continuous(breaks = seq(min(vacc_clean_dt$Year), max(vacc_clean_dt$Year), 3)) +
134 |
135 | # Aplicar tema
136 | theme_week4_social(base_family = "Lato", base_size = 10) +
137 |
138 | # Etiquetas y caption
139 | labs(
140 | title = plot_title,
141 | subtitle = plot_subtitle,
142 | x = "Año",
143 | # Y ya definido en scale_y_continuous
144 | caption = caption_day24
145 | ) +
146 | theme(legend.title = element_text(hjust = 0.5))
147 |
148 | # --- 6. Guardar Gráfico ---
149 | output_file <- file.path(output_path, "day_24_who_vaccination_esp.png")
150 | ggsave(
151 | filename = output_file,
152 | plot = gg_day24,
153 | width = 1200, height = 1200, units = "px", dpi = 150, bg = bg_col # Apaisado
154 | )
155 |
156 | message("Gráfico del Día 24 (WHO Vaccination) guardado en: ", normalizePath(output_file, mustWork = FALSE))
157 |
158 | # --- Fin day_24_who_vaccination ---
--------------------------------------------------------------------------------