diff --git a/404.html b/404.html index c15b097..af0745c 100644 --- a/404.html +++ b/404.html @@ -6,7 +6,7 @@
Résultats attendus :
Résultat attendu : création de l’indicateur artificialisation
pour les deux millésimes de majic (solution COGiter)
## Rows: 1,305
+## Rows: 1,304
## Columns: 4
## $ TypeZone <fct> Communes, Communes, Communes, Communes, Communes, Communes,…
## $ Zone <fct> "Abbaretz", "Aigrefeuille-sur-Maine", "Ancenis-Saint-Géréon…
## $ CodeZone <fct> 44001, 44002, 44003, 44005, 44006, 44007, 44009, 44010, 440…
## $ artif_2009 <dbl> 3064748, 2408844, 6859785, 6101987, 2379588, 3042688, 50259…
-## Rows: 1,305
+## Rows: 1,304
## Columns: 4
## $ TypeZone <fct> Communes, Communes, Communes, Communes, Communes, Communes,…
## $ Zone <fct> "Abbaretz", "Aigrefeuille-sur-Maine", "Ancenis-Saint-Géréon…
## $ CodeZone <fct> 44001, 44002, 44003, 44005, 44006, 44007, 44009, 44010, 440…
## $ artif_2014 <dbl> 3160057, 2485622, 7103107, 6496868, 2419875, 3105298, 52452…
Résultat attendu : création de les indicateurs pop_2009
et pop_2014
pour les deux millésimes de majic (solution COGiter)
-## Rows: 1,305
+## Rows: 1,304
## Columns: 4
## $ TypeZone <fct> Communes, Communes, Communes, Communes, Communes, Communes, C…
## $ Zone <fct> "Abbaretz", "Aigrefeuille-sur-Maine", "Ancenis-Saint-Géréon",…
## $ CodeZone <fct> 44001, 44002, 44003, 44005, 44006, 44007, 44009, 44010, 44012…
## $ pop_2009 <dbl> 1909, 3214, 10639, 5894, 1810, 2465, 8265, 3185, 2595, 2591, …
-## Rows: 1,305
+## Rows: 1,302
## Columns: 4
## $ TypeZone <fct> Communes, Communes, Communes, Communes, Communes, Communes, C…
## $ Zone <fct> "Abbaretz", "Aigrefeuille-sur-Maine", "Ancenis-Saint-Géréon",…
## $ CodeZone <fct> 44001, 44002, 44003, 44005, 44006, 44007, 44009, 44010, 44012…
## $ pop_2014 <dbl> 2042, 3714, 10783, 6680, 1830, 2601, 8747, 3086, 2769, 2927, …
Résultat attendu : jointude implicite sur idcom
et création de l’indicateur d'étalement urbain
(solution COGiter) :
-## Rows: 1,305
+## Rows: 1,304
## Columns: 11
## $ TypeZone <fct> Communes, Communes, Communes, Communes, Co…
## $ Zone <fct> "Abbaretz", "Aigrefeuille-sur-Maine", "Anc…
@@ -354,7 +359,7 @@ Chapitre 9 Exercice 6 : les donn
## $ ies <dbl> 0.446368388, 0.204882086, 2.620651010, 0.4…
## $ indicateur_etalement_avance <chr> "2a", "2a", "3", "2a", "3", "2a", "2a", "6…
Résultat attendu pour etalement_urbain_commune
:
-## Rows: 1,233
+## Rows: 1,232
## Columns: 11
## $ TypeZone <fct> Communes, Communes, Communes, Communes, Co…
## $ Zone <fct> "Abbaretz", "Aigrefeuille-sur-Maine", "Anc…
@@ -382,7 +387,7 @@ Chapitre 9 Exercice 6 : les donn
## $ ies <dbl> 0.3809548, 0.6067337, 7.5930733, 1.1128120…
## $ indicateur_etalement_avance <chr> "2a", "2a", "5", "3", "6", "3", "5", "2a",…
Résultat attendu pour le graphique (vu au M5) :
-
+
diff --git a/index.html b/index.html
index b832e5d..4e24dd9 100644
--- a/index.html
+++ b/index.html
@@ -6,7 +6,7 @@
Préparer ses données avec R et le Tidyverse
-
+
@@ -23,7 +23,7 @@
-
+
@@ -52,14 +52,15 @@
-
+
+
-
-
-
-
-
-
+
+
+
+
+
+
+
@@ -287,7 +292,7 @@
Préparer ses données avec R et le Tidyverse
-15 September 2023
+26 August 2024
Chapitre 1 Introduction
@@ -318,7 +323,7 @@ 1.1 Le parcours de formation
s’inscrire en envoyant un message vide à l’adresse sympa@developpement-durable.gouv.fr ;
-rejoindre le fil Ariane #utilisateurs_r.
+rejoindre le salon Tchap #utilisateurs_r.
diff --git a/le-tidyverse.html b/le-tidyverse.html
index 50439a9..25af208 100644
--- a/le-tidyverse.html
+++ b/le-tidyverse.html
@@ -6,7 +6,7 @@
Chapitre 2 Le tidyverse | Préparer ses données avec R et le Tidyverse
-
+
@@ -23,7 +23,7 @@
-
+
@@ -52,14 +52,15 @@
-
+
+
-
-
-
-
-
-
+
+
+
+
+
+
+
diff --git a/libs/crosstalk-1.2.0/css/crosstalk.min.css b/libs/crosstalk-1.2.1/css/crosstalk.min.css
similarity index 100%
rename from libs/crosstalk-1.2.0/css/crosstalk.min.css
rename to libs/crosstalk-1.2.1/css/crosstalk.min.css
diff --git a/libs/crosstalk-1.2.0/js/crosstalk.min.js b/libs/crosstalk-1.2.1/js/crosstalk.min.js
similarity index 100%
rename from libs/crosstalk-1.2.0/js/crosstalk.min.js
rename to libs/crosstalk-1.2.1/js/crosstalk.min.js
diff --git a/libs/datatables-binding-0.29/datatables.js b/libs/datatables-binding-0.33/datatables.js
similarity index 95%
rename from libs/datatables-binding-0.29/datatables.js
rename to libs/datatables-binding-0.33/datatables.js
index b930851..765b53c 100644
--- a/libs/datatables-binding-0.29/datatables.js
+++ b/libs/datatables-binding-0.33/datatables.js
@@ -348,6 +348,15 @@ HTMLWidgets.widget({
var table = $table.DataTable(options);
$el.data('datatable', table);
+ if ('rowGroup' in options) {
+ // Maintain RowGroup dataSrc when columns are reordered (#1109)
+ table.on('column-reorder', function(e, settings, details) {
+ var oldDataSrc = table.rowGroup().dataSrc();
+ var newDataSrc = details.mapping[oldDataSrc];
+ table.rowGroup().dataSrc(newDataSrc);
+ });
+ }
+
// Unregister previous Crosstalk event subscriptions, if they exist
if (instance.ctfilterSubscription) {
instance.ctfilterHandle.off("change", instance.ctfilterSubscription);
@@ -432,10 +441,13 @@ HTMLWidgets.widget({
regex = options.search.regex,
ci = options.search.caseInsensitive !== false;
}
+ // need to transpose the column index when colReorder is enabled
+ if (table.colReorder) i = table.colReorder.transpose(i);
return table.column(i).search(value, regex, !regex, ci);
};
if (data.filter !== 'none') {
+ if (!data.hasOwnProperty('filterSettings')) data.filterSettings = {};
filterRow.each(function(i, td) {
@@ -493,11 +505,13 @@ HTMLWidgets.widget({
$input.parent().hide(); $x.show().trigger('show'); filter[0].selectize.focus();
},
input: function() {
- if ($input.val() === '') filter[0].selectize.setValue([]);
+ var v1 = JSON.stringify(filter[0].selectize.getValue()), v2 = $input.val();
+ if (v1 === '[]') v1 = '';
+ if (v1 !== v2) filter[0].selectize.setValue(v2 === '' ? [] : JSON.parse(v2));
}
});
var $input2 = $x.children('select');
- filter = $input2.selectize({
+ filter = $input2.selectize($.extend({
options: $input2.data('options').map(function(v, i) {
return ({text: v, value: v});
}),
@@ -509,15 +523,14 @@ HTMLWidgets.widget({
if (value.length) $input.trigger('input');
$input.attr('title', $input.val());
if (server) {
- table.column(i).search(value.length ? JSON.stringify(value) : '').draw();
+ searchColumn(i, value.length ? JSON.stringify(value) : '').draw();
return;
}
// turn off filter if nothing selected
$td.data('filter', value.length > 0);
table.draw(); // redraw table, and filters will be applied
}
- });
- if (searchCol) filter[0].selectize.setValue(JSON.parse(searchCol));
+ }, data.filterSettings.select));
filter[0].selectize.on('blur', function() {
$x.hide().trigger('hide'); $input.parent().show(); $input.trigger('blur');
});
@@ -526,10 +539,12 @@ HTMLWidgets.widget({
var fun = function() {
searchColumn(i, $input.val()).draw();
};
- if (server) {
- fun = $.fn.dataTable.util.throttle(fun, options.searchDelay);
- }
- $input.on('input', fun);
+ // throttle searching for server-side processing
+ var throttledFun = $.fn.dataTable.util.throttle(fun, options.searchDelay);
+ $input.on('input', function(e, immediate) {
+ // always bypass throttling when immediate = true (via the updateSearch method)
+ (immediate || !server) ? fun() : throttledFun();
+ });
} else if (inArray(type, ['number', 'integer', 'date', 'time'])) {
var $x0 = $x;
$x = $x0.children('div').first();
@@ -615,13 +630,11 @@ HTMLWidgets.widget({
filter.val(v);
}
});
- var formatDate = function(d, isoFmt) {
+ var formatDate = function(d) {
d = scaleBack(d, scale);
if (type === 'number') return d;
if (type === 'integer') return parseInt(d);
var x = new Date(+d);
- var fmt = ('filterDateFmt' in data) ? data.filterDateFmt[i] : undefined;
- if (fmt !== undefined && isoFmt === false) return x[fmt.method].apply(x, fmt.params);
if (type === 'date') {
var pad0 = function(x) {
return ('0' + x).substr(-2, 2);
@@ -642,7 +655,7 @@ HTMLWidgets.widget({
start: [r1, r2],
range: {min: r1, max: r2},
connect: true
- }, opts));
+ }, opts, data.filterSettings.slider));
if (scale > 1) (function() {
var t1 = r1, t2 = r2;
var val = filter.val();
@@ -657,13 +670,28 @@ HTMLWidgets.widget({
start: [t1, t2],
range: {min: t1, max: t2},
connect: true
- }, opts), true);
+ }, opts, data.filterSettings.slider), true);
val = filter.val();
}
r1 = t1; r2 = t2;
})();
+ // format with active column renderer, if defined
+ var colDef = data.options.columnDefs.find(function(def) {
+ return (def.targets === i || inArray(i, def.targets)) && 'render' in def;
+ });
var updateSliderText = function(v1, v2) {
- $span1.text(formatDate(v1, false)); $span2.text(formatDate(v2, false));
+ // we only know how to use function renderers
+ if (colDef && typeof colDef.render === 'function') {
+ var restore = function(v) {
+ v = scaleBack(v, scale);
+ return inArray(type, ['date', 'time']) ? new Date(+v) : v;
+ }
+ $span1.text(colDef.render(restore(v1), 'display'));
+ $span2.text(colDef.render(restore(v2), 'display'));
+ } else {
+ $span1.text(formatDate(v1));
+ $span2.text(formatDate(v2));
+ }
};
updateSliderText(r1, r2);
var updateSlider = function(e) {
@@ -680,7 +708,7 @@ HTMLWidgets.widget({
updateSliderText(val[0], val[1]);
if (e.type === 'slide') return; // no searching when sliding only
if (server) {
- table.column(i).search($td.data('filter') ? ival : '').draw();
+ searchColumn(i, $td.data('filter') ? ival : '').draw();
return;
}
table.draw();
@@ -696,7 +724,7 @@ HTMLWidgets.widget({
// processing
if (server) {
// if a search string has been pre-set, search now
- if (searchCol) searchColumn(i, searchCol).draw();
+ if (searchCol) $input.trigger('input').trigger('change');
return;
}
@@ -742,15 +770,7 @@ HTMLWidgets.widget({
$.fn.dataTable.ext.search.push(customFilter);
// search for the preset search strings if it is non-empty
- if (searchCol) {
- if (inArray(type, ['factor', 'logical'])) {
- filter[0].selectize.setValue(JSON.parse(searchCol));
- } else if (type === 'character') {
- $input.trigger('input');
- } else if (inArray(type, ['number', 'integer', 'date', 'time'])) {
- $input.trigger('change');
- }
- }
+ if (searchCol) $input.trigger('input').trigger('change');
});
@@ -1012,6 +1032,9 @@ HTMLWidgets.widget({
updateColsSelected();
updateCellsSelected();
})
+ updateRowsSelected();
+ updateColsSelected();
+ updateCellsSelected();
}
var selMode = data.selection.mode, selTarget = data.selection.target;
@@ -1370,7 +1393,7 @@ HTMLWidgets.widget({
changeInput('cell_clicked', {});
// do not trigger table selection when clicking on links unless they have classes
- table.on('click.dt', 'tbody td a', function(e) {
+ table.on('mousedown.dt', 'tbody td a', function(e) {
if (this.className === '') e.stopPropagation();
});
@@ -1398,8 +1421,9 @@ HTMLWidgets.widget({
console.log('The search keyword for column ' + i + ' is undefined')
return;
}
- $(td).find('input').first().val(v);
- searchColumn(i, v);
+ // Update column search string and values on linked filter widgets.
+ // 'input' for factor and char filters, 'change' for numeric filters.
+ $(td).find('input').first().val(v).trigger('input', [true]).trigger('change');
});
table.draw();
}
diff --git a/libs/dt-core-1.13.4/css/jquery.dataTables.min.css b/libs/dt-core-1.13.4/css/jquery.dataTables.min.css
deleted file mode 100644
index aff1ca6..0000000
--- a/libs/dt-core-1.13.4/css/jquery.dataTables.min.css
+++ /dev/null
@@ -1 +0,0 @@
-:root{--dt-row-selected: 13, 110, 253;--dt-row-selected-text: 255, 255, 255;--dt-row-selected-link: 9, 10, 11}table.dataTable td.dt-control{text-align:center;cursor:pointer}table.dataTable td.dt-control:before{height:1em;width:1em;margin-top:-9px;display:inline-block;color:white;border:.15em solid white;border-radius:1em;box-shadow:0 0 .2em #444;box-sizing:content-box;text-align:center;text-indent:0 !important;font-family:"Courier New",Courier,monospace;line-height:1em;content:"+";background-color:#31b131}table.dataTable tr.dt-hasChild td.dt-control:before{content:"-";background-color:#d33333}table.dataTable thead>tr>th.sorting,table.dataTable thead>tr>th.sorting_asc,table.dataTable thead>tr>th.sorting_desc,table.dataTable thead>tr>th.sorting_asc_disabled,table.dataTable thead>tr>th.sorting_desc_disabled,table.dataTable thead>tr>td.sorting,table.dataTable thead>tr>td.sorting_asc,table.dataTable thead>tr>td.sorting_desc,table.dataTable thead>tr>td.sorting_asc_disabled,table.dataTable thead>tr>td.sorting_desc_disabled{cursor:pointer;position:relative;padding-right:26px}table.dataTable thead>tr>th.sorting:before,table.dataTable thead>tr>th.sorting:after,table.dataTable thead>tr>th.sorting_asc:before,table.dataTable thead>tr>th.sorting_asc:after,table.dataTable thead>tr>th.sorting_desc:before,table.dataTable thead>tr>th.sorting_desc:after,table.dataTable thead>tr>th.sorting_asc_disabled:before,table.dataTable thead>tr>th.sorting_asc_disabled:after,table.dataTable thead>tr>th.sorting_desc_disabled:before,table.dataTable thead>tr>th.sorting_desc_disabled:after,table.dataTable thead>tr>td.sorting:before,table.dataTable thead>tr>td.sorting:after,table.dataTable thead>tr>td.sorting_asc:before,table.dataTable thead>tr>td.sorting_asc:after,table.dataTable thead>tr>td.sorting_desc:before,table.dataTable thead>tr>td.sorting_desc:after,table.dataTable thead>tr>td.sorting_asc_disabled:before,table.dataTable thead>tr>td.sorting_asc_disabled:after,table.dataTable thead>tr>td.sorting_desc_disabled:before,table.dataTable thead>tr>td.sorting_desc_disabled:after{position:absolute;display:block;opacity:.125;right:10px;line-height:9px;font-size:.8em}table.dataTable thead>tr>th.sorting:before,table.dataTable thead>tr>th.sorting_asc:before,table.dataTable thead>tr>th.sorting_desc:before,table.dataTable thead>tr>th.sorting_asc_disabled:before,table.dataTable thead>tr>th.sorting_desc_disabled:before,table.dataTable thead>tr>td.sorting:before,table.dataTable thead>tr>td.sorting_asc:before,table.dataTable thead>tr>td.sorting_desc:before,table.dataTable thead>tr>td.sorting_asc_disabled:before,table.dataTable thead>tr>td.sorting_desc_disabled:before{bottom:50%;content:"▲";content:"▲"/""}table.dataTable thead>tr>th.sorting:after,table.dataTable thead>tr>th.sorting_asc:after,table.dataTable thead>tr>th.sorting_desc:after,table.dataTable thead>tr>th.sorting_asc_disabled:after,table.dataTable thead>tr>th.sorting_desc_disabled:after,table.dataTable thead>tr>td.sorting:after,table.dataTable thead>tr>td.sorting_asc:after,table.dataTable thead>tr>td.sorting_desc:after,table.dataTable thead>tr>td.sorting_asc_disabled:after,table.dataTable thead>tr>td.sorting_desc_disabled:after{top:50%;content:"▼";content:"▼"/""}table.dataTable thead>tr>th.sorting_asc:before,table.dataTable thead>tr>th.sorting_desc:after,table.dataTable thead>tr>td.sorting_asc:before,table.dataTable thead>tr>td.sorting_desc:after{opacity:.6}table.dataTable thead>tr>th.sorting_desc_disabled:after,table.dataTable thead>tr>th.sorting_asc_disabled:before,table.dataTable thead>tr>td.sorting_desc_disabled:after,table.dataTable thead>tr>td.sorting_asc_disabled:before{display:none}table.dataTable thead>tr>th:active,table.dataTable thead>tr>td:active{outline:none}div.dataTables_scrollBody>table.dataTable>thead>tr>th:before,div.dataTables_scrollBody>table.dataTable>thead>tr>th:after,div.dataTables_scrollBody>table.dataTable>thead>tr>td:before,div.dataTables_scrollBody>table.dataTable>thead>tr>td:after{display:none}div.dataTables_processing{position:absolute;top:50%;left:50%;width:200px;margin-left:-100px;margin-top:-26px;text-align:center;padding:2px}div.dataTables_processing>div:last-child{position:relative;width:80px;height:15px;margin:1em auto}div.dataTables_processing>div:last-child>div{position:absolute;top:0;width:13px;height:13px;border-radius:50%;background:rgb(13, 110, 253);background:rgb(var(--dt-row-selected));animation-timing-function:cubic-bezier(0, 1, 1, 0)}div.dataTables_processing>div:last-child>div:nth-child(1){left:8px;animation:datatables-loader-1 .6s infinite}div.dataTables_processing>div:last-child>div:nth-child(2){left:8px;animation:datatables-loader-2 .6s infinite}div.dataTables_processing>div:last-child>div:nth-child(3){left:32px;animation:datatables-loader-2 .6s infinite}div.dataTables_processing>div:last-child>div:nth-child(4){left:56px;animation:datatables-loader-3 .6s infinite}@keyframes datatables-loader-1{0%{transform:scale(0)}100%{transform:scale(1)}}@keyframes datatables-loader-3{0%{transform:scale(1)}100%{transform:scale(0)}}@keyframes datatables-loader-2{0%{transform:translate(0, 0)}100%{transform:translate(24px, 0)}}table.dataTable.nowrap th,table.dataTable.nowrap td{white-space:nowrap}table.dataTable th.dt-left,table.dataTable td.dt-left{text-align:left}table.dataTable th.dt-center,table.dataTable td.dt-center,table.dataTable td.dataTables_empty{text-align:center}table.dataTable th.dt-right,table.dataTable td.dt-right{text-align:right}table.dataTable th.dt-justify,table.dataTable td.dt-justify{text-align:justify}table.dataTable th.dt-nowrap,table.dataTable td.dt-nowrap{white-space:nowrap}table.dataTable thead th,table.dataTable thead td,table.dataTable tfoot th,table.dataTable tfoot td{text-align:left}table.dataTable thead th.dt-head-left,table.dataTable thead td.dt-head-left,table.dataTable tfoot th.dt-head-left,table.dataTable tfoot td.dt-head-left{text-align:left}table.dataTable thead th.dt-head-center,table.dataTable thead td.dt-head-center,table.dataTable tfoot th.dt-head-center,table.dataTable tfoot td.dt-head-center{text-align:center}table.dataTable thead th.dt-head-right,table.dataTable thead td.dt-head-right,table.dataTable tfoot th.dt-head-right,table.dataTable tfoot td.dt-head-right{text-align:right}table.dataTable thead th.dt-head-justify,table.dataTable thead td.dt-head-justify,table.dataTable tfoot th.dt-head-justify,table.dataTable tfoot td.dt-head-justify{text-align:justify}table.dataTable thead th.dt-head-nowrap,table.dataTable thead td.dt-head-nowrap,table.dataTable tfoot th.dt-head-nowrap,table.dataTable tfoot td.dt-head-nowrap{white-space:nowrap}table.dataTable tbody th.dt-body-left,table.dataTable tbody td.dt-body-left{text-align:left}table.dataTable tbody th.dt-body-center,table.dataTable tbody td.dt-body-center{text-align:center}table.dataTable tbody th.dt-body-right,table.dataTable tbody td.dt-body-right{text-align:right}table.dataTable tbody th.dt-body-justify,table.dataTable tbody td.dt-body-justify{text-align:justify}table.dataTable tbody th.dt-body-nowrap,table.dataTable tbody td.dt-body-nowrap{white-space:nowrap}table.dataTable{width:100%;margin:0 auto;clear:both;border-collapse:separate;border-spacing:0}table.dataTable thead th,table.dataTable tfoot th{font-weight:bold}table.dataTable thead th,table.dataTable thead td{padding:10px;border-bottom:1px solid rgba(0, 0, 0, 0.3)}table.dataTable thead th:active,table.dataTable thead td:active{outline:none}table.dataTable tfoot th,table.dataTable tfoot td{padding:10px 10px 6px 10px;border-top:1px solid rgba(0, 0, 0, 0.3)}table.dataTable tbody tr{background-color:transparent}table.dataTable tbody tr.selected>*{box-shadow:inset 0 0 0 9999px rgba(13, 110, 253, 0.9);box-shadow:inset 0 0 0 9999px rgba(var(--dt-row-selected), 0.9);color:rgb(255, 255, 255);color:rgb(var(--dt-row-selected-text))}table.dataTable tbody tr.selected a{color:rgb(9, 10, 11);color:rgb(var(--dt-row-selected-link))}table.dataTable tbody th,table.dataTable tbody td{padding:8px 10px}table.dataTable.row-border tbody th,table.dataTable.row-border tbody td,table.dataTable.display tbody th,table.dataTable.display tbody td{border-top:1px solid rgba(0, 0, 0, 0.15)}table.dataTable.row-border tbody tr:first-child th,table.dataTable.row-border tbody tr:first-child td,table.dataTable.display tbody tr:first-child th,table.dataTable.display tbody tr:first-child td{border-top:none}table.dataTable.cell-border tbody th,table.dataTable.cell-border tbody td{border-top:1px solid rgba(0, 0, 0, 0.15);border-right:1px solid rgba(0, 0, 0, 0.15)}table.dataTable.cell-border tbody tr th:first-child,table.dataTable.cell-border tbody tr td:first-child{border-left:1px solid rgba(0, 0, 0, 0.15)}table.dataTable.cell-border tbody tr:first-child th,table.dataTable.cell-border tbody tr:first-child td{border-top:none}table.dataTable.stripe>tbody>tr.odd>*,table.dataTable.display>tbody>tr.odd>*{box-shadow:inset 0 0 0 9999px rgba(0, 0, 0, 0.023)}table.dataTable.stripe>tbody>tr.odd.selected>*,table.dataTable.display>tbody>tr.odd.selected>*{box-shadow:inset 0 0 0 9999px rgba(13, 110, 253, 0.923);box-shadow:inset 0 0 0 9999px rgba(var(--dt-row-selected, 0.923))}table.dataTable.hover>tbody>tr:hover>*,table.dataTable.display>tbody>tr:hover>*{box-shadow:inset 0 0 0 9999px rgba(0, 0, 0, 0.035)}table.dataTable.hover>tbody>tr.selected:hover>*,table.dataTable.display>tbody>tr.selected:hover>*{box-shadow:inset 0 0 0 9999px #0d6efd !important;box-shadow:inset 0 0 0 9999px rgba(var(--dt-row-selected, 1)) !important}table.dataTable.order-column>tbody tr>.sorting_1,table.dataTable.order-column>tbody tr>.sorting_2,table.dataTable.order-column>tbody tr>.sorting_3,table.dataTable.display>tbody tr>.sorting_1,table.dataTable.display>tbody tr>.sorting_2,table.dataTable.display>tbody tr>.sorting_3{box-shadow:inset 0 0 0 9999px rgba(0, 0, 0, 0.019)}table.dataTable.order-column>tbody tr.selected>.sorting_1,table.dataTable.order-column>tbody tr.selected>.sorting_2,table.dataTable.order-column>tbody tr.selected>.sorting_3,table.dataTable.display>tbody tr.selected>.sorting_1,table.dataTable.display>tbody tr.selected>.sorting_2,table.dataTable.display>tbody tr.selected>.sorting_3{box-shadow:inset 0 0 0 9999px rgba(13, 110, 253, 0.919);box-shadow:inset 0 0 0 9999px rgba(var(--dt-row-selected, 0.919))}table.dataTable.display>tbody>tr.odd>.sorting_1,table.dataTable.order-column.stripe>tbody>tr.odd>.sorting_1{box-shadow:inset 0 0 0 9999px rgba(0, 0, 0, 0.054)}table.dataTable.display>tbody>tr.odd>.sorting_2,table.dataTable.order-column.stripe>tbody>tr.odd>.sorting_2{box-shadow:inset 0 0 0 9999px rgba(0, 0, 0, 0.047)}table.dataTable.display>tbody>tr.odd>.sorting_3,table.dataTable.order-column.stripe>tbody>tr.odd>.sorting_3{box-shadow:inset 0 0 0 9999px rgba(0, 0, 0, 0.039)}table.dataTable.display>tbody>tr.odd.selected>.sorting_1,table.dataTable.order-column.stripe>tbody>tr.odd.selected>.sorting_1{box-shadow:inset 0 0 0 9999px rgba(13, 110, 253, 0.954);box-shadow:inset 0 0 0 9999px rgba(var(--dt-row-selected, 0.954))}table.dataTable.display>tbody>tr.odd.selected>.sorting_2,table.dataTable.order-column.stripe>tbody>tr.odd.selected>.sorting_2{box-shadow:inset 0 0 0 9999px rgba(13, 110, 253, 0.947);box-shadow:inset 0 0 0 9999px rgba(var(--dt-row-selected, 0.947))}table.dataTable.display>tbody>tr.odd.selected>.sorting_3,table.dataTable.order-column.stripe>tbody>tr.odd.selected>.sorting_3{box-shadow:inset 0 0 0 9999px rgba(13, 110, 253, 0.939);box-shadow:inset 0 0 0 9999px rgba(var(--dt-row-selected, 0.939))}table.dataTable.display>tbody>tr.even>.sorting_1,table.dataTable.order-column.stripe>tbody>tr.even>.sorting_1{box-shadow:inset 0 0 0 9999px rgba(0, 0, 0, 0.019)}table.dataTable.display>tbody>tr.even>.sorting_2,table.dataTable.order-column.stripe>tbody>tr.even>.sorting_2{box-shadow:inset 0 0 0 9999px rgba(0, 0, 0, 0.011)}table.dataTable.display>tbody>tr.even>.sorting_3,table.dataTable.order-column.stripe>tbody>tr.even>.sorting_3{box-shadow:inset 0 0 0 9999px rgba(0, 0, 0, 0.003)}table.dataTable.display>tbody>tr.even.selected>.sorting_1,table.dataTable.order-column.stripe>tbody>tr.even.selected>.sorting_1{box-shadow:inset 0 0 0 9999px rgba(13, 110, 253, 0.919);box-shadow:inset 0 0 0 9999px rgba(var(--dt-row-selected, 0.919))}table.dataTable.display>tbody>tr.even.selected>.sorting_2,table.dataTable.order-column.stripe>tbody>tr.even.selected>.sorting_2{box-shadow:inset 0 0 0 9999px rgba(13, 110, 253, 0.911);box-shadow:inset 0 0 0 9999px rgba(var(--dt-row-selected, 0.911))}table.dataTable.display>tbody>tr.even.selected>.sorting_3,table.dataTable.order-column.stripe>tbody>tr.even.selected>.sorting_3{box-shadow:inset 0 0 0 9999px rgba(13, 110, 253, 0.903);box-shadow:inset 0 0 0 9999px rgba(var(--dt-row-selected, 0.903))}table.dataTable.display tbody tr:hover>.sorting_1,table.dataTable.order-column.hover tbody tr:hover>.sorting_1{box-shadow:inset 0 0 0 9999px rgba(0, 0, 0, 0.082)}table.dataTable.display tbody tr:hover>.sorting_2,table.dataTable.order-column.hover tbody tr:hover>.sorting_2{box-shadow:inset 0 0 0 9999px rgba(0, 0, 0, 0.074)}table.dataTable.display tbody tr:hover>.sorting_3,table.dataTable.order-column.hover tbody tr:hover>.sorting_3{box-shadow:inset 0 0 0 9999px rgba(0, 0, 0, 0.062)}table.dataTable.display tbody tr:hover.selected>.sorting_1,table.dataTable.order-column.hover tbody tr:hover.selected>.sorting_1{box-shadow:inset 0 0 0 9999px rgba(13, 110, 253, 0.982);box-shadow:inset 0 0 0 9999px rgba(var(--dt-row-selected, 0.982))}table.dataTable.display tbody tr:hover.selected>.sorting_2,table.dataTable.order-column.hover tbody tr:hover.selected>.sorting_2{box-shadow:inset 0 0 0 9999px rgba(13, 110, 253, 0.974);box-shadow:inset 0 0 0 9999px rgba(var(--dt-row-selected, 0.974))}table.dataTable.display tbody tr:hover.selected>.sorting_3,table.dataTable.order-column.hover tbody tr:hover.selected>.sorting_3{box-shadow:inset 0 0 0 9999px rgba(13, 110, 253, 0.962);box-shadow:inset 0 0 0 9999px rgba(var(--dt-row-selected, 0.962))}table.dataTable.no-footer{border-bottom:1px solid rgba(0, 0, 0, 0.3)}table.dataTable.compact thead th,table.dataTable.compact thead td,table.dataTable.compact tfoot th,table.dataTable.compact tfoot td,table.dataTable.compact tbody th,table.dataTable.compact tbody td{padding:4px}table.dataTable th,table.dataTable td{box-sizing:content-box}.dataTables_wrapper{position:relative;clear:both}.dataTables_wrapper .dataTables_length{float:left}.dataTables_wrapper .dataTables_length select{border:1px solid #aaa;border-radius:3px;padding:5px;background-color:transparent;padding:4px}.dataTables_wrapper .dataTables_filter{float:right;text-align:right}.dataTables_wrapper .dataTables_filter input{border:1px solid #aaa;border-radius:3px;padding:5px;background-color:transparent;margin-left:3px}.dataTables_wrapper .dataTables_info{clear:both;float:left;padding-top:.755em}.dataTables_wrapper .dataTables_paginate{float:right;text-align:right;padding-top:.25em}.dataTables_wrapper .dataTables_paginate .paginate_button{box-sizing:border-box;display:inline-block;min-width:1.5em;padding:.5em 1em;margin-left:2px;text-align:center;text-decoration:none !important;cursor:pointer;color:inherit !important;border:1px solid transparent;border-radius:2px;background:transparent}.dataTables_wrapper .dataTables_paginate .paginate_button.current,.dataTables_wrapper .dataTables_paginate .paginate_button.current:hover{color:inherit !important;border:1px solid rgba(0, 0, 0, 0.3);background-color:rgba(230, 230, 230, 0.1);background:-webkit-gradient(linear, left top, left bottom, color-stop(0%, rgba(230, 230, 230, 0.1)), color-stop(100%, rgba(0, 0, 0, 0.1)));background:-webkit-linear-gradient(top, rgba(230, 230, 230, 0.1) 0%, rgba(0, 0, 0, 0.1) 100%);background:-moz-linear-gradient(top, rgba(230, 230, 230, 0.1) 0%, rgba(0, 0, 0, 0.1) 100%);background:-ms-linear-gradient(top, rgba(230, 230, 230, 0.1) 0%, rgba(0, 0, 0, 0.1) 100%);background:-o-linear-gradient(top, rgba(230, 230, 230, 0.1) 0%, rgba(0, 0, 0, 0.1) 100%);background:linear-gradient(to bottom, rgba(230, 230, 230, 0.1) 0%, rgba(0, 0, 0, 0.1) 100%)}.dataTables_wrapper .dataTables_paginate .paginate_button.disabled,.dataTables_wrapper .dataTables_paginate .paginate_button.disabled:hover,.dataTables_wrapper .dataTables_paginate .paginate_button.disabled:active{cursor:default;color:#666 !important;border:1px solid transparent;background:transparent;box-shadow:none}.dataTables_wrapper .dataTables_paginate .paginate_button:hover{color:white !important;border:1px solid #111;background-color:#585858;background:-webkit-gradient(linear, left top, left bottom, color-stop(0%, #585858), color-stop(100%, #111));background:-webkit-linear-gradient(top, #585858 0%, #111 100%);background:-moz-linear-gradient(top, #585858 0%, #111 100%);background:-ms-linear-gradient(top, #585858 0%, #111 100%);background:-o-linear-gradient(top, #585858 0%, #111 100%);background:linear-gradient(to bottom, #585858 0%, #111 100%)}.dataTables_wrapper .dataTables_paginate .paginate_button:active{outline:none;background-color:#2b2b2b;background:-webkit-gradient(linear, left top, left bottom, color-stop(0%, #2b2b2b), color-stop(100%, #0c0c0c));background:-webkit-linear-gradient(top, #2b2b2b 0%, #0c0c0c 100%);background:-moz-linear-gradient(top, #2b2b2b 0%, #0c0c0c 100%);background:-ms-linear-gradient(top, #2b2b2b 0%, #0c0c0c 100%);background:-o-linear-gradient(top, #2b2b2b 0%, #0c0c0c 100%);background:linear-gradient(to bottom, #2b2b2b 0%, #0c0c0c 100%);box-shadow:inset 0 0 3px #111}.dataTables_wrapper .dataTables_paginate .ellipsis{padding:0 1em}.dataTables_wrapper .dataTables_length,.dataTables_wrapper .dataTables_filter,.dataTables_wrapper .dataTables_info,.dataTables_wrapper .dataTables_processing,.dataTables_wrapper .dataTables_paginate{color:inherit}.dataTables_wrapper .dataTables_scroll{clear:both}.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody{-webkit-overflow-scrolling:touch}.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody>table>thead>tr>th,.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody>table>thead>tr>td,.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody>table>tbody>tr>th,.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody>table>tbody>tr>td{vertical-align:middle}.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody>table>thead>tr>th>div.dataTables_sizing,.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody>table>thead>tr>td>div.dataTables_sizing,.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody>table>tbody>tr>th>div.dataTables_sizing,.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody>table>tbody>tr>td>div.dataTables_sizing{height:0;overflow:hidden;margin:0 !important;padding:0 !important}.dataTables_wrapper.no-footer .dataTables_scrollBody{border-bottom:1px solid rgba(0, 0, 0, 0.3)}.dataTables_wrapper.no-footer div.dataTables_scrollHead table.dataTable,.dataTables_wrapper.no-footer div.dataTables_scrollBody>table{border-bottom:none}.dataTables_wrapper:after{visibility:hidden;display:block;content:"";clear:both;height:0}@media screen and (max-width: 767px){.dataTables_wrapper .dataTables_info,.dataTables_wrapper .dataTables_paginate{float:none;text-align:center}.dataTables_wrapper .dataTables_paginate{margin-top:.5em}}@media screen and (max-width: 640px){.dataTables_wrapper .dataTables_length,.dataTables_wrapper .dataTables_filter{float:none;text-align:center}.dataTables_wrapper .dataTables_filter{margin-top:.5em}}
diff --git a/libs/dt-core-1.13.4/js/jquery.dataTables.min.js b/libs/dt-core-1.13.4/js/jquery.dataTables.min.js
deleted file mode 100644
index c89263c..0000000
--- a/libs/dt-core-1.13.4/js/jquery.dataTables.min.js
+++ /dev/null
@@ -1,4 +0,0 @@
-/*! DataTables 1.13.4
- * ©2008-2023 SpryMedia Ltd - datatables.net/license
- */
-!function(n){"use strict";var a;"function"==typeof define&&define.amd?define(["jquery"],function(t){return n(t,window,document)}):"object"==typeof exports?(a=require("jquery"),"undefined"!=typeof window?module.exports=function(t,e){return t=t||window,e=e||a(t),n(e,t,t.document)}:n(a,window,window.document)):window.DataTable=n(jQuery,window,document)}(function(P,j,y,N){"use strict";function d(t){var e=parseInt(t,10);return!isNaN(e)&&isFinite(t)?e:null}function l(t,e,n){var a=typeof t,r="string"==a;return"number"==a||"bigint"==a||!!h(t)||(e&&r&&(t=G(t,e)),n&&r&&(t=t.replace(q,"")),!isNaN(parseFloat(t))&&isFinite(t))}function a(t,e,n){var a;return!!h(t)||(h(a=t)||"string"==typeof a)&&!!l(t.replace(V,""),e,n)||null}function m(t,e,n,a){var r=[],o=0,i=e.length;if(a!==N)for(;o").appendTo(l)),h.nTHead=n[0],l.children("tbody")),n=(0===a.length&&(a=P("").insertAfter(n)),h.nTBody=a[0],l.children("tfoot"));if(0===(n=0===n.length&&0 ").appendTo(l):n).length||0===n.children().length?l.addClass(p.sNoFooter):0/g,X=/^\d{2,4}[\.\/\-]\d{1,2}[\.\/\-]\d{1,2}([T ]{1}\d{1,2}[:\.]\d{2}([\.:]\d{2})?)?$/,J=new RegExp("(\\"+["/",".","*","+","?","|","(",")","[","]","{","}","\\","$","^","-"].join("|\\")+")","g"),q=/['\u00A0,$£€¥%\u2009\u202F\u20BD\u20a9\u20BArfkɃΞ]/gi,h=function(t){return!t||!0===t||"-"===t},G=function(t,e){return c[e]||(c[e]=new RegExp(Ot(e),"g")),"string"==typeof t&&"."!==e?t.replace(/\./g,"").replace(c[e],"."):t},H=function(t,e,n){var a=[],r=0,o=t.length;if(n!==N)for(;r ").css({position:"fixed",top:0,left:-1*P(j).scrollLeft(),height:1,width:1,overflow:"hidden"}).append(P("").css({position:"absolute",top:1,left:1,width:100,overflow:"scroll"}).append(P("").css({width:"100%",height:10}))).appendTo("body")).children()).children(),e.barWidth=a[0].offsetWidth-a[0].clientWidth,e.bScrollOversize=100===r[0].offsetWidth&&100!==a[0].clientWidth,e.bScrollbarLeft=1!==Math.round(r.offset().left),e.bBounding=!!n[0].getBoundingClientRect().width,n.remove()),P.extend(t.oBrowser,w.__browser),t.oScroll.iBarWidth=w.__browser.barWidth}function et(t,e,n,a,r,o){var i,l=a,s=!1;for(n!==N&&(i=n,s=!0);l!==r;)t.hasOwnProperty(l)&&(i=s?e(i,t[l],l,t):t[l],s=!0,l+=o);return i}function nt(t,e){var n=w.defaults.column,a=t.aoColumns.length,n=P.extend({},w.models.oColumn,n,{nTh:e||y.createElement("th"),sTitle:n.sTitle||(e?e.innerHTML:""),aDataSort:n.aDataSort||[a],mData:n.mData||a,idx:a}),n=(t.aoColumns.push(n),t.aoPreSearchCols);n[a]=P.extend({},w.models.oSearch,n[a]),at(t,a,P(e).data())}function at(t,e,n){function a(t){return"string"==typeof t&&-1!==t.indexOf("@")}var e=t.aoColumns[e],r=t.oClasses,o=P(e.nTh),i=(!e.sWidthOrig&&(e.sWidthOrig=o.attr("width")||null,u=(o.attr("style")||"").match(/width:\s*(\d+[pxem%]+)/))&&(e.sWidthOrig=u[1]),n!==N&&null!==n&&(Q(n),C(w.defaults.column,n,!0),n.mDataProp===N||n.mData||(n.mData=n.mDataProp),n.sType&&(e._sManualType=n.sType),n.className&&!n.sClass&&(n.sClass=n.className),n.sClass&&o.addClass(n.sClass),u=e.sClass,P.extend(e,n),F(e,n,"sWidth","sWidthOrig"),u!==e.sClass&&(e.sClass=u+" "+e.sClass),n.iDataSort!==N&&(e.aDataSort=[n.iDataSort]),F(e,n,"aDataSort")),e.mData),l=A(i),s=e.mRender?A(e.mRender):null,u=(e._bAttrSrc=P.isPlainObject(i)&&(a(i.sort)||a(i.type)||a(i.filter)),e._setter=null,e.fnGetData=function(t,e,n){var a=l(t,e,N,n);return s&&e?s(a,e,t,n):a},e.fnSetData=function(t,e,n){return b(i)(t,e,n)},"number"==typeof i||e._isArrayHost||(t._rowReadObject=!0),t.oFeatures.bSort||(e.bSortable=!1,o.addClass(r.sSortableNone)),-1!==P.inArray("asc",e.asSorting)),n=-1!==P.inArray("desc",e.asSorting);e.bSortable&&(u||n)?u&&!n?(e.sSortingClass=r.sSortableAsc,e.sSortingClassJUI=r.sSortJUIAscAllowed):!u&&n?(e.sSortingClass=r.sSortableDesc,e.sSortingClassJUI=r.sSortJUIDescAllowed):(e.sSortingClass=r.sSortable,e.sSortingClassJUI=r.sSortJUI):(e.sSortingClass=r.sSortableNone,e.sSortingClassJUI="")}function O(t){if(!1!==t.oFeatures.bAutoWidth){var e=t.aoColumns;ee(t);for(var n=0,a=e.length;ne&&t[r]--;-1!=a&&n===N&&t.splice(a,1)}function bt(n,a,t,e){function r(t,e){for(;t.childNodes.length;)t.removeChild(t.firstChild);t.innerHTML=S(n,a,e,"display")}var o,i,l=n.aoData[a];if("dom"!==t&&(t&&"auto"!==t||"dom"!==l.src)){var s=l.anCells;if(s)if(e!==N)r(s[e],e);else for(o=0,i=s.length;o").appendTo(r)),c=0,f=s.length;c=s.fnRecordsDisplay()?0:l,s.iInitDisplayStart=-1);var n=R(t,"aoPreDrawCallback","preDraw",[t]);if(-1!==P.inArray(!1,n))D(t,!1);else{var a=[],r=0,o=t.asStripeClasses,i=o.length,l=t.oLanguage,s="ssp"==E(t),u=t.aiDisplay,n=t._iDisplayStart,c=t.fnDisplayEnd();if(t.bDrawing=!0,t.bDeferLoading)t.bDeferLoading=!1,t.iDraw++,D(t,!1);else if(s){if(!t.bDestroying&&!e)return void xt(t)}else t.iDraw++;if(0!==u.length)for(var f=s?t.aoData.length:c,d=s?0:n;d ",{class:i?o[0]:""}).append(P(" ",{valign:"top",colSpan:T(t),class:t.oClasses.sRowEmpty}).html(e))[0]}R(t,"aoHeaderCallback","header",[P(t.nTHead).children("tr")[0],ht(t),n,c,u]),R(t,"aoFooterCallback","footer",[P(t.nTFoot).children("tr")[0],ht(t),n,c,u]);s=P(t.nTBody);s.children().detach(),s.append(P(a)),R(t,"aoDrawCallback","draw",[t]),t.bSorted=!1,t.bFiltered=!1,t.bDrawing=!1}}function u(t,e){var n=t.oFeatures,a=n.bSort,n=n.bFilter;a&&ie(t),n?Rt(t,t.oPreviousSearch):t.aiDisplay=t.aiDisplayMaster.slice(),!0!==e&&(t._iDisplayStart=0),t._drawHold=e,v(t),t._drawHold=!1}function _t(t){for(var e,n,a,r,o,i,l,s=t.oClasses,u=P(t.nTable),u=P("").insertBefore(u),c=t.oFeatures,f=P("",{id:t.sTableId+"_wrapper",class:s.sWrapper+(t.nTFoot?"":" "+s.sNoFooter)}),d=(t.nHolding=u[0],t.nTableWrapper=f[0],t.nTableReinsertBefore=t.nTable.nextSibling,t.sDom.split("")),h=0;h ")[0],"'"==(r=d[h+1])||'"'==r){for(o="",i=2;d[h+i]!=r;)o+=d[h+i],i++;"H"==o?o=s.sJUIHeader:"F"==o&&(o=s.sJUIFooter),-1!=o.indexOf(".")?(l=o.split("."),a.id=l[0].substr(1,l[0].length-1),a.className=l[1]):"#"==o.charAt(0)?a.id=o.substr(1,o.length-1):a.className=o,h+=i}f.append(a),f=P(a)}else if(">"==n)f=f.parent();else if("l"==n&&c.bPaginate&&c.bLengthChange)e=$t(t);else if("f"==n&&c.bFilter)e=Lt(t);else if("r"==n&&c.bProcessing)e=Zt(t);else if("t"==n)e=Kt(t);else if("i"==n&&c.bInfo)e=Ut(t);else if("p"==n&&c.bPaginate)e=zt(t);else if(0!==w.ext.feature.length)for(var p=w.ext.feature,g=0,b=p.length;g',s=(s=r.sSearch).match(/_INPUT_/)?s.replace("_INPUT_",l):s+l,l=P("",{id:i.f?null:a+"_filter",class:t.sFilter}).append(P("").append(s)),t=null!==n.searchDelay?n.searchDelay:"ssp"===E(n)?400:0,u=P("input",l).val(o.sSearch).attr("placeholder",r.sSearchPlaceholder).on("keyup.DT search.DT input.DT paste.DT cut.DT",t?ne(e,t):e).on("mouseup",function(t){setTimeout(function(){e.call(u[0],t)},10)}).on("keypress.DT",function(t){if(13==t.keyCode)return!1}).attr("aria-controls",a);return P(n.nTable).on("search.dt.DT",function(t,e){if(n===e)try{u[0]!==y.activeElement&&u.val(o.sSearch)}catch(t){}}),l[0]}function Rt(t,e,n){function a(t){o.sSearch=t.sSearch,o.bRegex=t.bRegex,o.bSmart=t.bSmart,o.bCaseInsensitive=t.bCaseInsensitive,o.return=t.return}function r(t){return t.bEscapeRegex!==N?!t.bEscapeRegex:t.bRegex}var o=t.oPreviousSearch,i=t.aoPreSearchCols;if(lt(t),"ssp"!=E(t)){Nt(t,e.sSearch,n,r(e),e.bSmart,e.bCaseInsensitive,e.return),a(e);for(var l=0;le.length||0!==e.indexOf(r)||t.bSorted)&&(t.aiDisplay=o.slice()),i=t.aiDisplay,s=0;s")[0],Mt=kt.textContent!==N;function Wt(t){for(var e,n,a,r,o,i=t.aoColumns,l=!1,s=0,u=t.aoData.length;s",{class:t.oClasses.sInfo,id:n?null:e+"_info"});return n||(t.aoDrawCallback.push({fn:Vt,sName:"information"}),a.attr("role","status").attr("aria-live","polite"),P(t.nTable).attr("aria-describedby",e+"_info")),a[0]}function Vt(t){var e,n,a,r,o,i,l=t.aanFeatures.i;0!==l.length&&(i=t.oLanguage,e=t._iDisplayStart+1,n=t.fnDisplayEnd(),a=t.fnRecordsTotal(),o=(r=t.fnRecordsDisplay())?i.sInfo:i.sInfoEmpty,r!==a&&(o+=" "+i.sInfoFiltered),o=Xt(t,o+=i.sInfoPostFix),null!==(i=i.fnInfoCallback)&&(o=i.call(t.oInstance,t,e,n,a,r,o)),P(l).html(o))}function Xt(t,e){var n=t.fnFormatNumber,a=t._iDisplayStart+1,r=t._iDisplayLength,o=t.fnRecordsDisplay(),i=-1===r;return e.replace(/_START_/g,n.call(t,a)).replace(/_END_/g,n.call(t,t.fnDisplayEnd())).replace(/_MAX_/g,n.call(t,t.fnRecordsTotal())).replace(/_TOTAL_/g,n.call(t,o)).replace(/_PAGE_/g,n.call(t,i?1:Math.ceil(a/r))).replace(/_PAGES_/g,n.call(t,i?1:Math.ceil(o/r)))}function Jt(n){var a,t,e,r=n.iInitDisplayStart,o=n.aoColumns,i=n.oFeatures,l=n.bDeferLoading;if(n.bInitialised){for(_t(n),yt(n),Dt(n,n.aoHeader),Dt(n,n.aoFooter),D(n,!0),i.bAutoWidth&&ee(n),a=0,t=o.length;a",{name:e+"_length","aria-controls":e,class:t.sLengthSelect}),s=0,u=o.length;s ").addClass(t.sLength);return a.aanFeatures.l||(c[0].id=e+"_length"),c.children().append(a.oLanguage.sLengthMenu.replace("_MENU_",l[0].outerHTML)),P("select",c).val(a._iDisplayLength).on("change.DT",function(t){Gt(a,P(this).val()),v(a)}),P(a.nTable).on("length.dt.DT",function(t,e,n){a===e&&P("select",c).val(n)}),c[0]}function zt(t){function c(t){v(t)}var e=t.sPaginationType,f=w.ext.pager[e],d="function"==typeof f,e=P("").addClass(t.oClasses.sPaging+e)[0],h=t.aanFeatures;return d||f.fnInit(t,e,c),h.p||(e.id=t.sTableId+"_paginate",t.aoDrawCallback.push({fn:function(t){if(d)for(var e=t._iDisplayStart,n=t._iDisplayLength,a=t.fnRecordsDisplay(),r=-1===n,o=r?0:Math.ceil(e/n),i=r?1:Math.ceil(a/n),l=f(o,i),s=0,u=h.p.length;s",{id:t.aanFeatures.r?null:t.sTableId+"_processing",class:t.oClasses.sProcessing,role:"status"}).html(t.oLanguage.sProcessing).append("").insertBefore(t.nTable)[0]}function D(t,e){t.oFeatures.bProcessing&&P(t.aanFeatures.r).css("display",e?"block":"none"),R(t,null,"processing",[t,e])}function Kt(t){var e,n,a,r,o,i,l,s,u,c,f,d,h=P(t.nTable),p=t.oScroll;return""===p.sX&&""===p.sY?t.nTable:(e=p.sX,n=p.sY,a=t.oClasses,o=(r=h.children("caption")).length?r[0]._captionSide:null,s=P(h[0].cloneNode(!1)),i=P(h[0].cloneNode(!1)),u=function(t){return t?M(t):null},(l=h.children("tfoot")).length||(l=null),s=P(f="",{class:a.sScrollWrapper}).append(P(f,{class:a.sScrollHead}).css({overflow:"hidden",position:"relative",border:0,width:e?u(e):"100%"}).append(P(f,{class:a.sScrollHeadInner}).css({"box-sizing":"content-box",width:p.sXInner||"100%"}).append(s.removeAttr("id").css("margin-left",0).append("top"===o?r:null).append(h.children("thead"))))).append(P(f,{class:a.sScrollBody}).css({position:"relative",overflow:"auto",width:u(e)}).append(h)),l&&s.append(P(f,{class:a.sScrollFoot}).css({overflow:"hidden",border:0,width:e?u(e):"100%"}).append(P(f,{class:a.sScrollFootInner}).append(i.removeAttr("id").css("margin-left",0).append("bottom"===o?r:null).append(h.children("tfoot"))))),u=s.children(),c=u[0],f=u[1],d=l?u[2]:null,e&&P(f).on("scroll.DT",function(t){var e=this.scrollLeft;c.scrollLeft=e,l&&(d.scrollLeft=e)}),P(f).css("max-height",n),p.bCollapse||P(f).css("height",n),t.nScrollHead=c,t.nScrollBody=f,t.nScrollFoot=d,t.aoDrawCallback.push({fn:Qt,sName:"scrolling"}),s[0])}function Qt(n){function t(t){(t=t.style).paddingTop="0",t.paddingBottom="0",t.borderTopWidth="0",t.borderBottomWidth="0",t.height=0}var e,a,r,o,i,l=n.oScroll,s=l.sX,u=l.sXInner,c=l.sY,l=l.iBarWidth,f=P(n.nScrollHead),d=f[0].style,h=f.children("div"),p=h[0].style,h=h.children("table"),g=n.nScrollBody,b=P(g),m=g.style,S=P(n.nScrollFoot).children("div"),v=S.children("table"),y=P(n.nTHead),D=P(n.nTable),_=D[0],w=_.style,C=n.nTFoot?P(n.nTFoot):null,T=n.oBrowser,x=T.bScrollOversize,A=(H(n.aoColumns,"nTh"),[]),I=[],F=[],L=[],R=g.scrollHeight>g.clientHeight;n.scrollBarVis!==R&&n.scrollBarVis!==N?(n.scrollBarVis=R,O(n)):(n.scrollBarVis=R,D.children("thead, tfoot").remove(),C&&(R=C.clone().prependTo(D),i=C.find("tr"),a=R.find("tr"),R.find("[id]").removeAttr("id")),R=y.clone().prependTo(D),y=y.find("tr"),e=R.find("tr"),R.find("th, td").removeAttr("tabindex"),R.find("[id]").removeAttr("id"),s||(m.width="100%",f[0].style.width="100%"),P.each(Ct(n,R),function(t,e){r=rt(n,t),e.style.width=n.aoColumns[r].sWidth}),C&&k(function(t){t.style.width=""},a),f=D.outerWidth(),""===s?(w.width="100%",x&&(D.find("tbody").height()>g.offsetHeight||"scroll"==b.css("overflow-y"))&&(w.width=M(D.outerWidth()-l)),f=D.outerWidth()):""!==u&&(w.width=M(u),f=D.outerWidth()),k(t,e),k(function(t){var e=j.getComputedStyle?j.getComputedStyle(t).width:M(P(t).width());F.push(t.innerHTML),A.push(e)},e),k(function(t,e){t.style.width=A[e]},y),P(e).css("height",0),C&&(k(t,a),k(function(t){L.push(t.innerHTML),I.push(M(P(t).css("width")))},a),k(function(t,e){t.style.width=I[e]},i),P(a).height(0)),k(function(t,e){t.innerHTML=''+F[e]+"",t.childNodes[0].style.height="0",t.childNodes[0].style.overflow="hidden",t.style.width=A[e]},e),C&&k(function(t,e){t.innerHTML=''+L[e]+"",t.childNodes[0].style.height="0",t.childNodes[0].style.overflow="hidden",t.style.width=I[e]},a),Math.round(D.outerWidth())g.offsetHeight||"scroll"==b.css("overflow-y")?f+l:f,x&&(g.scrollHeight>g.offsetHeight||"scroll"==b.css("overflow-y"))&&(w.width=M(o-l)),""!==s&&""===u||W(n,1,"Possible column misalignment",6)):o="100%",m.width=M(o),d.width=M(o),C&&(n.nScrollFoot.style.width=M(o)),c||x&&(m.height=M(_.offsetHeight+l)),R=D.outerWidth(),h[0].style.width=M(R),p.width=M(R),y=D.height()>g.clientHeight||"scroll"==b.css("overflow-y"),p[i="padding"+(T.bScrollbarLeft?"Left":"Right")]=y?l+"px":"0px",C&&(v[0].style.width=M(R),S[0].style.width=M(R),S[0].style[i]=y?l+"px":"0px"),D.children("colgroup").insertBefore(D.children("thead")),b.trigger("scroll"),!n.bSorted&&!n.bFiltered||n._drawHold||(g.scrollTop=0))}function k(t,e,n){for(var a,r,o=0,i=0,l=e.length;i/g;function ee(t){var e,n,a=t.nTable,r=t.aoColumns,o=t.oScroll,i=o.sY,l=o.sX,o=o.sXInner,s=r.length,u=it(t,"bVisible"),c=P("th",t.nTHead),f=a.getAttribute("width"),d=a.parentNode,h=!1,p=t.oBrowser,g=p.bScrollOversize,b=a.style.width;for(b&&-1!==b.indexOf("%")&&(f=b),D=0;D ").appendTo(b.find("tbody")));for(b.find("thead, tfoot").remove(),b.append(P(t.nTHead).clone()).append(P(t.nTFoot).clone()),b.find("tfoot th, tfoot td").css("width",""),c=Ct(t,b.find("thead")[0]),D=0;D ").css({width:e.sWidthOrig,margin:0,padding:0,border:0,height:1}));if(t.aoData.length)for(D=0;D").css(l||i?{position:"absolute",top:0,left:0,height:1,right:0,overflow:"hidden"}:{}).append(b).appendTo(d),y=(l&&o?b.width(o):l?(b.css("width","auto"),b.removeAttr("width"),b.width() ").css("width",M(t)).appendTo(e||y.body))[0].offsetWidth,t.remove(),e):0}function re(t,e){var n,a=oe(t,e);return a<0?null:(n=t.aoData[a]).nTr?n.anCells[e]:P(" ").html(S(t,a,e,"display"))[0]}function oe(t,e){for(var n,a=-1,r=-1,o=0,i=t.aoData.length;oa&&(a=n.length,r=o);return r}function M(t){return null===t?"0px":"number"==typeof t?t<0?"0px":t+"px":t.match(/\d$/)?t+"px":t}function I(t){function e(t){t.length&&!Array.isArray(t[0])?h.push(t):P.merge(h,t)}var n,a,r,o,i,l,s,u=[],c=t.aoColumns,f=t.aaSortingFixed,d=P.isPlainObject(f),h=[];for(Array.isArray(f)&&e(f),d&&f.pre&&e(f.pre),e(t.aaSorting),d&&f.post&&e(f.post),n=0;n/g,""),u=i.nTh;u.removeAttribute("aria-sort"),i=i.bSortable?s+("asc"===(0=o.length?[0,e[1]]:e)})),t.search!==N&&P.extend(n.oPreviousSearch,Bt(t.search)),t.columns){for(a=0,r=t.columns.length;a ").addClass(e),P("td",n).addClass(e).html(t)[0].colSpan=T(o),l.push(n[0]))}var l=[];i(e,n),t._details&&t._details.detach(),t._details=P(l),t._detailsShow&&t._details.insertAfter(t.nTr)}function xe(t,e){var n=t.context;if(n.length&&t.length){var a=n[0].aoData[t[0]];if(a._details){(a._detailsShow=e)?(a._details.insertAfter(a.nTr),P(a.nTr).addClass("dt-hasChild")):(a._details.detach(),P(a.nTr).removeClass("dt-hasChild")),R(n[0],null,"childRow",[e,t.row(t[0])]);var s=n[0],r=new B(s),a=".dt.DT_details",e="draw"+a,t="column-sizing"+a,a="destroy"+a,u=s.aoData;if(r.off(e+" "+t+" "+a),H(u,"_details").length>0){r.on(e,function(t,e){if(s!==e)return;r.rows({page:"current"}).eq(0).each(function(t){var e=u[t];if(e._detailsShow)e._details.insertAfter(e.nTr)})});r.on(t,function(t,e,n,a){if(s!==e)return;var r,o=T(e);for(var i=0,l=u.length;it?new B(e[t],this[t]):null},filter:function(t){var e=[];if(o.filter)e=o.filter.call(this,t,this);else for(var n=0,a=this.length;n").appendTo(t);p(u,n)}else{switch(g=null,b=n,a=c.iTabIndex,n){case"ellipsis":t.append('…');break;case"first":g=S.sFirst,0===d&&(a=-1,b+=" "+o);break;case"previous":g=S.sPrevious,0===d&&(a=-1,b+=" "+o);break;case"next":g=S.sNext,0!==h&&d!==h-1||(a=-1,b+=" "+o);break;case"last":g=S.sLast,0!==h&&d!==h-1||(a=-1,b+=" "+o);break;default:g=c.fnFormatNumber(n+1),b=d===n?m.sPageButtonActive:""}null!==g&&(u=c.oInit.pagingTag||"a",r=-1!==b.indexOf(o),me(P("<"+u+">",{class:m.sPageButton+" "+b,"aria-controls":c.sTableId,"aria-disabled":r?"true":null,"aria-label":v[n],"aria-role":"link","aria-current":b===m.sPageButtonActive?"page":null,"data-dt-idx":n,tabindex:a,id:0===f&&"string"==typeof n?c.sTableId+"_"+n:null}).html(g).appendTo(t),{action:n},i))}}var g,b,n,m=c.oClasses,S=c.oLanguage.oPaginate,v=c.oLanguage.oAria.paginate||{};try{n=P(t).find(y.activeElement).data("dt-idx")}catch(t){}p(P(t).empty(),e),n!==N&&P(t).find("[data-dt-idx="+n+"]").trigger("focus")}}}),P.extend(w.ext.type.detect,[function(t,e){e=e.oLanguage.sDecimal;return l(t,e)?"num"+e:null},function(t,e){var n;return(!t||t instanceof Date||X.test(t))&&(null!==(n=Date.parse(t))&&!isNaN(n)||h(t))?"date":null},function(t,e){e=e.oLanguage.sDecimal;return l(t,e,!0)?"num-fmt"+e:null},function(t,e){e=e.oLanguage.sDecimal;return a(t,e)?"html-num"+e:null},function(t,e){e=e.oLanguage.sDecimal;return a(t,e,!0)?"html-num-fmt"+e:null},function(t,e){return h(t)||"string"==typeof t&&-1!==t.indexOf("<")?"html":null}]),P.extend(w.ext.type.search,{html:function(t){return h(t)?t:"string"==typeof t?t.replace(U," ").replace(V,""):""},string:function(t){return!h(t)&&"string"==typeof t?t.replace(U," "):t}});function ke(t,e,n,a){var r;return 0===t||t&&"-"!==t?"number"==(r=typeof t)||"bigint"==r?t:+(t=(t=e?G(t,e):t).replace&&(n&&(t=t.replace(n,"")),a)?t.replace(a,""):t):-1/0}function Me(n){P.each({num:function(t){return ke(t,n)},"num-fmt":function(t){return ke(t,n,q)},"html-num":function(t){return ke(t,n,V)},"html-num-fmt":function(t){return ke(t,n,V,q)}},function(t,e){p.type.order[t+n+"-pre"]=e,t.match(/^html\-/)&&(p.type.search[t+n]=p.type.search.html)})}P.extend(p.type.order,{"date-pre":function(t){t=Date.parse(t);return isNaN(t)?-1/0:t},"html-pre":function(t){return h(t)?"":t.replace?t.replace(/<.*?>/g,"").toLowerCase():t+""},"string-pre":function(t){return h(t)?"":"string"==typeof t?t.toLowerCase():t.toString?t.toString():""},"string-asc":function(t,e){return t ").addClass(l.sSortJUIWrapper).append(o.contents()).append(P("").addClass(l.sSortIcon+" "+i.sSortingClassJUI)).appendTo(o),P(r.nTable).on("order.dt.DT",function(t,e,n,a){r===e&&(e=i.idx,o.removeClass(l.sSortAsc+" "+l.sSortDesc).addClass("asc"==a[e]?l.sSortAsc:"desc"==a[e]?l.sSortDesc:i.sSortingClass),o.find("span."+l.sSortIcon).removeClass(l.sSortJUIAsc+" "+l.sSortJUIDesc+" "+l.sSortJUI+" "+l.sSortJUIAscAllowed+" "+l.sSortJUIDescAllowed).addClass("asc"==a[e]?l.sSortJUIAsc:"desc"==a[e]?l.sSortJUIDesc:i.sSortingClassJUI))})}}});function We(t){return"string"==typeof(t=Array.isArray(t)?t.join(","):t)?t.replace(/&/g,"&").replace(//g,">").replace(/"/g,"""):t}function Ee(t,e,n,a,r){return j.moment?t[e](r):j.luxon?t[n](r):a?t[a](r):t}var Be=!1;function Ue(t,e,n){var a;if(j.moment){if(!(a=j.moment.utc(t,e,n,!0)).isValid())return null}else if(j.luxon){if(!(a=e&&"string"==typeof t?j.luxon.DateTime.fromFormat(t,e):j.luxon.DateTime.fromISO(t)).isValid)return null;a.setLocale(n)}else e?(Be||alert("DataTables warning: Formatted date without Moment.js or Luxon - https://datatables.net/tn/17"),Be=!0):a=new Date(t);return a}function Ve(s){return function(a,r,o,i){0===arguments.length?(o="en",a=r=null):1===arguments.length?(o="en",r=a,a=null):2===arguments.length&&(o=r,r=a,a=null);var l="datetime-"+r;return w.ext.type.order[l]||(w.ext.type.detect.unshift(function(t){return t===l&&l}),w.ext.type.order[l+"-asc"]=function(t,e){t=t.valueOf(),e=e.valueOf();return t===e?0:ttr>th.sorting,table.dataTable thead>tr>th.sorting_asc,table.dataTable thead>tr>th.sorting_desc,table.dataTable thead>tr>th.sorting_asc_disabled,table.dataTable thead>tr>th.sorting_desc_disabled,table.dataTable thead>tr>td.sorting,table.dataTable thead>tr>td.sorting_asc,table.dataTable thead>tr>td.sorting_desc,table.dataTable thead>tr>td.sorting_asc_disabled,table.dataTable thead>tr>td.sorting_desc_disabled{cursor:pointer;position:relative;padding-right:26px}table.dataTable thead>tr>th.sorting:before,table.dataTable thead>tr>th.sorting:after,table.dataTable thead>tr>th.sorting_asc:before,table.dataTable thead>tr>th.sorting_asc:after,table.dataTable thead>tr>th.sorting_desc:before,table.dataTable thead>tr>th.sorting_desc:after,table.dataTable thead>tr>th.sorting_asc_disabled:before,table.dataTable thead>tr>th.sorting_asc_disabled:after,table.dataTable thead>tr>th.sorting_desc_disabled:before,table.dataTable thead>tr>th.sorting_desc_disabled:after,table.dataTable thead>tr>td.sorting:before,table.dataTable thead>tr>td.sorting:after,table.dataTable thead>tr>td.sorting_asc:before,table.dataTable thead>tr>td.sorting_asc:after,table.dataTable thead>tr>td.sorting_desc:before,table.dataTable thead>tr>td.sorting_desc:after,table.dataTable thead>tr>td.sorting_asc_disabled:before,table.dataTable thead>tr>td.sorting_asc_disabled:after,table.dataTable thead>tr>td.sorting_desc_disabled:before,table.dataTable thead>tr>td.sorting_desc_disabled:after{position:absolute;display:block;opacity:.125;right:10px;line-height:9px;font-size:.8em}table.dataTable thead>tr>th.sorting:before,table.dataTable thead>tr>th.sorting_asc:before,table.dataTable thead>tr>th.sorting_desc:before,table.dataTable thead>tr>th.sorting_asc_disabled:before,table.dataTable thead>tr>th.sorting_desc_disabled:before,table.dataTable thead>tr>td.sorting:before,table.dataTable thead>tr>td.sorting_asc:before,table.dataTable thead>tr>td.sorting_desc:before,table.dataTable thead>tr>td.sorting_asc_disabled:before,table.dataTable thead>tr>td.sorting_desc_disabled:before{bottom:50%;content:"▲";content:"▲"/""}table.dataTable thead>tr>th.sorting:after,table.dataTable thead>tr>th.sorting_asc:after,table.dataTable thead>tr>th.sorting_desc:after,table.dataTable thead>tr>th.sorting_asc_disabled:after,table.dataTable thead>tr>th.sorting_desc_disabled:after,table.dataTable thead>tr>td.sorting:after,table.dataTable thead>tr>td.sorting_asc:after,table.dataTable thead>tr>td.sorting_desc:after,table.dataTable thead>tr>td.sorting_asc_disabled:after,table.dataTable thead>tr>td.sorting_desc_disabled:after{top:50%;content:"▼";content:"▼"/""}table.dataTable thead>tr>th.sorting_asc:before,table.dataTable thead>tr>th.sorting_desc:after,table.dataTable thead>tr>td.sorting_asc:before,table.dataTable thead>tr>td.sorting_desc:after{opacity:.6}table.dataTable thead>tr>th.sorting_desc_disabled:after,table.dataTable thead>tr>th.sorting_asc_disabled:before,table.dataTable thead>tr>td.sorting_desc_disabled:after,table.dataTable thead>tr>td.sorting_asc_disabled:before{display:none}table.dataTable thead>tr>th:active,table.dataTable thead>tr>td:active{outline:none}div.dataTables_scrollBody>table.dataTable>thead>tr>th:before,div.dataTables_scrollBody>table.dataTable>thead>tr>th:after,div.dataTables_scrollBody>table.dataTable>thead>tr>td:before,div.dataTables_scrollBody>table.dataTable>thead>tr>td:after{display:none}div.dataTables_processing{position:absolute;top:50%;left:50%;width:200px;margin-left:-100px;margin-top:-26px;text-align:center;padding:2px}div.dataTables_processing>div:last-child{position:relative;width:80px;height:15px;margin:1em auto}div.dataTables_processing>div:last-child>div{position:absolute;top:0;width:13px;height:13px;border-radius:50%;background:rgb(13, 110, 253);background:rgb(var(--dt-row-selected));animation-timing-function:cubic-bezier(0, 1, 1, 0)}div.dataTables_processing>div:last-child>div:nth-child(1){left:8px;animation:datatables-loader-1 .6s infinite}div.dataTables_processing>div:last-child>div:nth-child(2){left:8px;animation:datatables-loader-2 .6s infinite}div.dataTables_processing>div:last-child>div:nth-child(3){left:32px;animation:datatables-loader-2 .6s infinite}div.dataTables_processing>div:last-child>div:nth-child(4){left:56px;animation:datatables-loader-3 .6s infinite}@keyframes datatables-loader-1{0%{transform:scale(0)}100%{transform:scale(1)}}@keyframes datatables-loader-3{0%{transform:scale(1)}100%{transform:scale(0)}}@keyframes datatables-loader-2{0%{transform:translate(0, 0)}100%{transform:translate(24px, 0)}}table.dataTable.nowrap th,table.dataTable.nowrap td{white-space:nowrap}table.dataTable th.dt-left,table.dataTable td.dt-left{text-align:left}table.dataTable th.dt-center,table.dataTable td.dt-center,table.dataTable td.dataTables_empty{text-align:center}table.dataTable th.dt-right,table.dataTable td.dt-right{text-align:right}table.dataTable th.dt-justify,table.dataTable td.dt-justify{text-align:justify}table.dataTable th.dt-nowrap,table.dataTable td.dt-nowrap{white-space:nowrap}table.dataTable thead th,table.dataTable thead td,table.dataTable tfoot th,table.dataTable tfoot td{text-align:left}table.dataTable thead th.dt-head-left,table.dataTable thead td.dt-head-left,table.dataTable tfoot th.dt-head-left,table.dataTable tfoot td.dt-head-left{text-align:left}table.dataTable thead th.dt-head-center,table.dataTable thead td.dt-head-center,table.dataTable tfoot th.dt-head-center,table.dataTable tfoot td.dt-head-center{text-align:center}table.dataTable thead th.dt-head-right,table.dataTable thead td.dt-head-right,table.dataTable tfoot th.dt-head-right,table.dataTable tfoot td.dt-head-right{text-align:right}table.dataTable thead th.dt-head-justify,table.dataTable thead td.dt-head-justify,table.dataTable tfoot th.dt-head-justify,table.dataTable tfoot td.dt-head-justify{text-align:justify}table.dataTable thead th.dt-head-nowrap,table.dataTable thead td.dt-head-nowrap,table.dataTable tfoot th.dt-head-nowrap,table.dataTable tfoot td.dt-head-nowrap{white-space:nowrap}table.dataTable tbody th.dt-body-left,table.dataTable tbody td.dt-body-left{text-align:left}table.dataTable tbody th.dt-body-center,table.dataTable tbody td.dt-body-center{text-align:center}table.dataTable tbody th.dt-body-right,table.dataTable tbody td.dt-body-right{text-align:right}table.dataTable tbody th.dt-body-justify,table.dataTable tbody td.dt-body-justify{text-align:justify}table.dataTable tbody th.dt-body-nowrap,table.dataTable tbody td.dt-body-nowrap{white-space:nowrap}table.dataTable{width:100%;margin:0 auto;clear:both;border-collapse:separate;border-spacing:0}table.dataTable thead th,table.dataTable tfoot th{font-weight:bold}table.dataTable>thead>tr>th,table.dataTable>thead>tr>td{padding:10px;border-bottom:1px solid rgba(0, 0, 0, 0.3)}table.dataTable>thead>tr>th:active,table.dataTable>thead>tr>td:active{outline:none}table.dataTable>tfoot>tr>th,table.dataTable>tfoot>tr>td{padding:10px 10px 6px 10px;border-top:1px solid rgba(0, 0, 0, 0.3)}table.dataTable tbody tr{background-color:transparent}table.dataTable tbody tr.selected>*{box-shadow:inset 0 0 0 9999px rgba(13, 110, 253, 0.9);box-shadow:inset 0 0 0 9999px rgba(var(--dt-row-selected), 0.9);color:rgb(255, 255, 255);color:rgb(var(--dt-row-selected-text))}table.dataTable tbody tr.selected a{color:rgb(9, 10, 11);color:rgb(var(--dt-row-selected-link))}table.dataTable tbody th,table.dataTable tbody td{padding:8px 10px}table.dataTable.row-border>tbody>tr>th,table.dataTable.row-border>tbody>tr>td,table.dataTable.display>tbody>tr>th,table.dataTable.display>tbody>tr>td{border-top:1px solid rgba(0, 0, 0, 0.15)}table.dataTable.row-border>tbody>tr:first-child>th,table.dataTable.row-border>tbody>tr:first-child>td,table.dataTable.display>tbody>tr:first-child>th,table.dataTable.display>tbody>tr:first-child>td{border-top:none}table.dataTable.row-border>tbody>tr.selected+tr.selected>td,table.dataTable.display>tbody>tr.selected+tr.selected>td{border-top-color:#0262ef}table.dataTable.cell-border>tbody>tr>th,table.dataTable.cell-border>tbody>tr>td{border-top:1px solid rgba(0, 0, 0, 0.15);border-right:1px solid rgba(0, 0, 0, 0.15)}table.dataTable.cell-border>tbody>tr>th:first-child,table.dataTable.cell-border>tbody>tr>td:first-child{border-left:1px solid rgba(0, 0, 0, 0.15)}table.dataTable.cell-border>tbody>tr:first-child>th,table.dataTable.cell-border>tbody>tr:first-child>td{border-top:none}table.dataTable.stripe>tbody>tr.odd>*,table.dataTable.display>tbody>tr.odd>*{box-shadow:inset 0 0 0 9999px rgba(0, 0, 0, 0.023);box-shadow:inset 0 0 0 9999px rgba(var(--dt-row-stripe), 0.023)}table.dataTable.stripe>tbody>tr.odd.selected>*,table.dataTable.display>tbody>tr.odd.selected>*{box-shadow:inset 0 0 0 9999px rgba(13, 110, 253, 0.923);box-shadow:inset 0 0 0 9999px rgba(var(--dt-row-selected), 0.923)}table.dataTable.hover>tbody>tr:hover>*,table.dataTable.display>tbody>tr:hover>*{box-shadow:inset 0 0 0 9999px rgba(0, 0, 0, 0.035);box-shadow:inset 0 0 0 9999px rgba(var(--dt-row-hover), 0.035)}table.dataTable.hover>tbody>tr.selected:hover>*,table.dataTable.display>tbody>tr.selected:hover>*{box-shadow:inset 0 0 0 9999px #0d6efd !important;box-shadow:inset 0 0 0 9999px rgba(var(--dt-row-selected), 1) !important}table.dataTable.order-column>tbody tr>.sorting_1,table.dataTable.order-column>tbody tr>.sorting_2,table.dataTable.order-column>tbody tr>.sorting_3,table.dataTable.display>tbody tr>.sorting_1,table.dataTable.display>tbody tr>.sorting_2,table.dataTable.display>tbody tr>.sorting_3{box-shadow:inset 0 0 0 9999px rgba(0, 0, 0, 0.019);box-shadow:inset 0 0 0 9999px rgba(var(--dt-column-ordering), 0.019)}table.dataTable.order-column>tbody tr.selected>.sorting_1,table.dataTable.order-column>tbody tr.selected>.sorting_2,table.dataTable.order-column>tbody tr.selected>.sorting_3,table.dataTable.display>tbody tr.selected>.sorting_1,table.dataTable.display>tbody tr.selected>.sorting_2,table.dataTable.display>tbody tr.selected>.sorting_3{box-shadow:inset 0 0 0 9999px rgba(13, 110, 253, 0.919);box-shadow:inset 0 0 0 9999px rgba(var(--dt-row-selected), 0.919)}table.dataTable.display>tbody>tr.odd>.sorting_1,table.dataTable.order-column.stripe>tbody>tr.odd>.sorting_1{box-shadow:inset 0 0 0 9999px rgba(0, 0, 0, 0.054);box-shadow:inset 0 0 0 9999px rgba(var(--dt-column-ordering), 0.054)}table.dataTable.display>tbody>tr.odd>.sorting_2,table.dataTable.order-column.stripe>tbody>tr.odd>.sorting_2{box-shadow:inset 0 0 0 9999px rgba(0, 0, 0, 0.047);box-shadow:inset 0 0 0 9999px rgba(var(--dt-column-ordering), 0.047)}table.dataTable.display>tbody>tr.odd>.sorting_3,table.dataTable.order-column.stripe>tbody>tr.odd>.sorting_3{box-shadow:inset 0 0 0 9999px rgba(0, 0, 0, 0.039);box-shadow:inset 0 0 0 9999px rgba(var(--dt-column-ordering), 0.039)}table.dataTable.display>tbody>tr.odd.selected>.sorting_1,table.dataTable.order-column.stripe>tbody>tr.odd.selected>.sorting_1{box-shadow:inset 0 0 0 9999px rgba(13, 110, 253, 0.954);box-shadow:inset 0 0 0 9999px rgba(var(--dt-row-selected), 0.954)}table.dataTable.display>tbody>tr.odd.selected>.sorting_2,table.dataTable.order-column.stripe>tbody>tr.odd.selected>.sorting_2{box-shadow:inset 0 0 0 9999px rgba(13, 110, 253, 0.947);box-shadow:inset 0 0 0 9999px rgba(var(--dt-row-selected), 0.947)}table.dataTable.display>tbody>tr.odd.selected>.sorting_3,table.dataTable.order-column.stripe>tbody>tr.odd.selected>.sorting_3{box-shadow:inset 0 0 0 9999px rgba(13, 110, 253, 0.939);box-shadow:inset 0 0 0 9999px rgba(var(--dt-row-selected), 0.939)}table.dataTable.display>tbody>tr.even>.sorting_1,table.dataTable.order-column.stripe>tbody>tr.even>.sorting_1{box-shadow:inset 0 0 0 9999px rgba(0, 0, 0, 0.019);box-shadow:inset 0 0 0 9999px rgba(var(--dt-row-selected), 0.019)}table.dataTable.display>tbody>tr.even>.sorting_2,table.dataTable.order-column.stripe>tbody>tr.even>.sorting_2{box-shadow:inset 0 0 0 9999px rgba(0, 0, 0, 0.011);box-shadow:inset 0 0 0 9999px rgba(var(--dt-row-selected), 0.011)}table.dataTable.display>tbody>tr.even>.sorting_3,table.dataTable.order-column.stripe>tbody>tr.even>.sorting_3{box-shadow:inset 0 0 0 9999px rgba(0, 0, 0, 0.003);box-shadow:inset 0 0 0 9999px rgba(var(--dt-row-selected), 0.003)}table.dataTable.display>tbody>tr.even.selected>.sorting_1,table.dataTable.order-column.stripe>tbody>tr.even.selected>.sorting_1{box-shadow:inset 0 0 0 9999px rgba(13, 110, 253, 0.919);box-shadow:inset 0 0 0 9999px rgba(var(--dt-row-selected), 0.919)}table.dataTable.display>tbody>tr.even.selected>.sorting_2,table.dataTable.order-column.stripe>tbody>tr.even.selected>.sorting_2{box-shadow:inset 0 0 0 9999px rgba(13, 110, 253, 0.911);box-shadow:inset 0 0 0 9999px rgba(var(--dt-row-selected), 0.911)}table.dataTable.display>tbody>tr.even.selected>.sorting_3,table.dataTable.order-column.stripe>tbody>tr.even.selected>.sorting_3{box-shadow:inset 0 0 0 9999px rgba(13, 110, 253, 0.903);box-shadow:inset 0 0 0 9999px rgba(var(--dt-row-selected), 0.903)}table.dataTable.display tbody tr:hover>.sorting_1,table.dataTable.order-column.hover tbody tr:hover>.sorting_1{box-shadow:inset 0 0 0 9999px rgba(0, 0, 0, 0.082);box-shadow:inset 0 0 0 9999px rgba(var(--dt-row-hover), 0.082)}table.dataTable.display tbody tr:hover>.sorting_2,table.dataTable.order-column.hover tbody tr:hover>.sorting_2{box-shadow:inset 0 0 0 9999px rgba(0, 0, 0, 0.074);box-shadow:inset 0 0 0 9999px rgba(var(--dt-row-hover), 0.074)}table.dataTable.display tbody tr:hover>.sorting_3,table.dataTable.order-column.hover tbody tr:hover>.sorting_3{box-shadow:inset 0 0 0 9999px rgba(0, 0, 0, 0.062);box-shadow:inset 0 0 0 9999px rgba(var(--dt-row-hover), 0.062)}table.dataTable.display tbody tr:hover.selected>.sorting_1,table.dataTable.order-column.hover tbody tr:hover.selected>.sorting_1{box-shadow:inset 0 0 0 9999px rgba(13, 110, 253, 0.982);box-shadow:inset 0 0 0 9999px rgba(var(--dt-row-selected), 0.982)}table.dataTable.display tbody tr:hover.selected>.sorting_2,table.dataTable.order-column.hover tbody tr:hover.selected>.sorting_2{box-shadow:inset 0 0 0 9999px rgba(13, 110, 253, 0.974);box-shadow:inset 0 0 0 9999px rgba(var(--dt-row-selected), 0.974)}table.dataTable.display tbody tr:hover.selected>.sorting_3,table.dataTable.order-column.hover tbody tr:hover.selected>.sorting_3{box-shadow:inset 0 0 0 9999px rgba(13, 110, 253, 0.962);box-shadow:inset 0 0 0 9999px rgba(var(--dt-row-selected), 0.962)}table.dataTable.no-footer{border-bottom:1px solid rgba(0, 0, 0, 0.3)}table.dataTable.compact thead th,table.dataTable.compact thead td,table.dataTable.compact tfoot th,table.dataTable.compact tfoot td,table.dataTable.compact tbody th,table.dataTable.compact tbody td{padding:4px}table.dataTable th,table.dataTable td{box-sizing:content-box}.dataTables_wrapper{position:relative;clear:both}.dataTables_wrapper .dataTables_length{float:left}.dataTables_wrapper .dataTables_length select{border:1px solid #aaa;border-radius:3px;padding:5px;background-color:transparent;color:inherit;padding:4px}.dataTables_wrapper .dataTables_filter{float:right;text-align:right}.dataTables_wrapper .dataTables_filter input{border:1px solid #aaa;border-radius:3px;padding:5px;background-color:transparent;color:inherit;margin-left:3px}.dataTables_wrapper .dataTables_info{clear:both;float:left;padding-top:.755em}.dataTables_wrapper .dataTables_paginate{float:right;text-align:right;padding-top:.25em}.dataTables_wrapper .dataTables_paginate .paginate_button{box-sizing:border-box;display:inline-block;min-width:1.5em;padding:.5em 1em;margin-left:2px;text-align:center;text-decoration:none !important;cursor:pointer;color:inherit !important;border:1px solid transparent;border-radius:2px;background:transparent}.dataTables_wrapper .dataTables_paginate .paginate_button.current,.dataTables_wrapper .dataTables_paginate .paginate_button.current:hover{color:inherit !important;border:1px solid rgba(0, 0, 0, 0.3);background-color:rgba(0, 0, 0, 0.05);background:-webkit-gradient(linear, left top, left bottom, color-stop(0%, rgba(230, 230, 230, 0.05)), color-stop(100%, rgba(0, 0, 0, 0.05)));background:-webkit-linear-gradient(top, rgba(230, 230, 230, 0.05) 0%, rgba(0, 0, 0, 0.05) 100%);background:-moz-linear-gradient(top, rgba(230, 230, 230, 0.05) 0%, rgba(0, 0, 0, 0.05) 100%);background:-ms-linear-gradient(top, rgba(230, 230, 230, 0.05) 0%, rgba(0, 0, 0, 0.05) 100%);background:-o-linear-gradient(top, rgba(230, 230, 230, 0.05) 0%, rgba(0, 0, 0, 0.05) 100%);background:linear-gradient(to bottom, rgba(230, 230, 230, 0.05) 0%, rgba(0, 0, 0, 0.05) 100%)}.dataTables_wrapper .dataTables_paginate .paginate_button.disabled,.dataTables_wrapper .dataTables_paginate .paginate_button.disabled:hover,.dataTables_wrapper .dataTables_paginate .paginate_button.disabled:active{cursor:default;color:#666 !important;border:1px solid transparent;background:transparent;box-shadow:none}.dataTables_wrapper .dataTables_paginate .paginate_button:hover{color:white !important;border:1px solid #111;background-color:#111;background:-webkit-gradient(linear, left top, left bottom, color-stop(0%, #585858), color-stop(100%, #111));background:-webkit-linear-gradient(top, #585858 0%, #111 100%);background:-moz-linear-gradient(top, #585858 0%, #111 100%);background:-ms-linear-gradient(top, #585858 0%, #111 100%);background:-o-linear-gradient(top, #585858 0%, #111 100%);background:linear-gradient(to bottom, #585858 0%, #111 100%)}.dataTables_wrapper .dataTables_paginate .paginate_button:active{outline:none;background-color:#0c0c0c;background:-webkit-gradient(linear, left top, left bottom, color-stop(0%, #2b2b2b), color-stop(100%, #0c0c0c));background:-webkit-linear-gradient(top, #2b2b2b 0%, #0c0c0c 100%);background:-moz-linear-gradient(top, #2b2b2b 0%, #0c0c0c 100%);background:-ms-linear-gradient(top, #2b2b2b 0%, #0c0c0c 100%);background:-o-linear-gradient(top, #2b2b2b 0%, #0c0c0c 100%);background:linear-gradient(to bottom, #2b2b2b 0%, #0c0c0c 100%);box-shadow:inset 0 0 3px #111}.dataTables_wrapper .dataTables_paginate .ellipsis{padding:0 1em}.dataTables_wrapper .dataTables_length,.dataTables_wrapper .dataTables_filter,.dataTables_wrapper .dataTables_info,.dataTables_wrapper .dataTables_processing,.dataTables_wrapper .dataTables_paginate{color:inherit}.dataTables_wrapper .dataTables_scroll{clear:both}.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody{-webkit-overflow-scrolling:touch}.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody>table>thead>tr>th,.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody>table>thead>tr>td,.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody>table>tbody>tr>th,.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody>table>tbody>tr>td{vertical-align:middle}.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody>table>thead>tr>th>div.dataTables_sizing,.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody>table>thead>tr>td>div.dataTables_sizing,.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody>table>tbody>tr>th>div.dataTables_sizing,.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody>table>tbody>tr>td>div.dataTables_sizing{height:0;overflow:hidden;margin:0 !important;padding:0 !important}.dataTables_wrapper.no-footer .dataTables_scrollBody{border-bottom:1px solid rgba(0, 0, 0, 0.3)}.dataTables_wrapper.no-footer div.dataTables_scrollHead table.dataTable,.dataTables_wrapper.no-footer div.dataTables_scrollBody>table{border-bottom:none}.dataTables_wrapper:after{visibility:hidden;display:block;content:"";clear:both;height:0}@media screen and (max-width: 767px){.dataTables_wrapper .dataTables_info,.dataTables_wrapper .dataTables_paginate{float:none;text-align:center}.dataTables_wrapper .dataTables_paginate{margin-top:.5em}}@media screen and (max-width: 640px){.dataTables_wrapper .dataTables_length,.dataTables_wrapper .dataTables_filter{float:none;text-align:center}.dataTables_wrapper .dataTables_filter{margin-top:.5em}}html.dark{--dt-row-hover: 255, 255, 255;--dt-row-stripe: 255, 255, 255;--dt-column-ordering: 255, 255, 255}html.dark table.dataTable>thead>tr>th,html.dark table.dataTable>thead>tr>td{border-bottom:1px solid rgb(89, 91, 94)}html.dark table.dataTable>thead>tr>th:active,html.dark table.dataTable>thead>tr>td:active{outline:none}html.dark table.dataTable>tfoot>tr>th,html.dark table.dataTable>tfoot>tr>td{border-top:1px solid rgb(89, 91, 94)}html.dark table.dataTable.row-border>tbody>tr>th,html.dark table.dataTable.row-border>tbody>tr>td,html.dark table.dataTable.display>tbody>tr>th,html.dark table.dataTable.display>tbody>tr>td{border-top:1px solid rgb(64, 67, 70)}html.dark table.dataTable.row-border>tbody>tr.selected+tr.selected>td,html.dark table.dataTable.display>tbody>tr.selected+tr.selected>td{border-top-color:#0257d5}html.dark table.dataTable.cell-border>tbody>tr>th,html.dark table.dataTable.cell-border>tbody>tr>td{border-top:1px solid rgb(64, 67, 70);border-right:1px solid rgb(64, 67, 70)}html.dark table.dataTable.cell-border>tbody>tr>th:first-child,html.dark table.dataTable.cell-border>tbody>tr>td:first-child{border-left:1px solid rgb(64, 67, 70)}html.dark .dataTables_wrapper .dataTables_filter input,html.dark .dataTables_wrapper .dataTables_length select{border:1px solid rgba(255, 255, 255, 0.2);background-color:var(--dt-html-background)}html.dark .dataTables_wrapper .dataTables_paginate .paginate_button.current,html.dark .dataTables_wrapper .dataTables_paginate .paginate_button.current:hover{border:1px solid rgb(89, 91, 94);background:rgba(255, 255, 255, 0.15)}html.dark .dataTables_wrapper .dataTables_paginate .paginate_button.disabled,html.dark .dataTables_wrapper .dataTables_paginate .paginate_button.disabled:hover,html.dark .dataTables_wrapper .dataTables_paginate .paginate_button.disabled:active{color:#666 !important}html.dark .dataTables_wrapper .dataTables_paginate .paginate_button:hover{border:1px solid rgb(53, 53, 53);background:rgb(53, 53, 53)}html.dark .dataTables_wrapper .dataTables_paginate .paginate_button:active{background:#3a3a3a}
diff --git a/libs/dt-core-1.13.6/js/jquery.dataTables.min.js b/libs/dt-core-1.13.6/js/jquery.dataTables.min.js
new file mode 100644
index 0000000..f786b0d
--- /dev/null
+++ b/libs/dt-core-1.13.6/js/jquery.dataTables.min.js
@@ -0,0 +1,4 @@
+/*! DataTables 1.13.6
+ * ©2008-2023 SpryMedia Ltd - datatables.net/license
+ */
+!function(n){"use strict";var a;"function"==typeof define&&define.amd?define(["jquery"],function(t){return n(t,window,document)}):"object"==typeof exports?(a=require("jquery"),"undefined"==typeof window?module.exports=function(t,e){return t=t||window,e=e||a(t),n(e,t,t.document)}:n(a,window,window.document)):window.DataTable=n(jQuery,window,document)}(function(P,j,v,H){"use strict";function d(t){var e=parseInt(t,10);return!isNaN(e)&&isFinite(t)?e:null}function l(t,e,n){var a=typeof t,r="string"==a;return"number"==a||"bigint"==a||!!h(t)||(e&&r&&(t=$(t,e)),n&&r&&(t=t.replace(q,"")),!isNaN(parseFloat(t))&&isFinite(t))}function a(t,e,n){var a;return!!h(t)||(h(a=t)||"string"==typeof a)&&!!l(t.replace(V,"").replace(/
-
+
+
-
-
-
-
-
-
+
+
+
+
+
+
+
@@ -310,8 +315,8 @@ 4.1.1 {readxl} : lire des donnée
sitadel <- read_excel("extdata/ROES_201702.xls", sheet = "AUT_REG",
col_types = c ("text","text","numeric","numeric","numeric","numeric"))
datatable(sitadel)
-
-
+
+
4.1.2 read_delim() : lire des fichiers plats
@@ -344,8 +349,8 @@ 4.2.1 Exemple site de l’INSEE,
<- read_excel("extdata/base-cc-tourisme-2019-geo2019.xls",
enq_tourisme sheet = "COM", skip = 5)
datatable(head(enq_tourisme), options = list(dom = 't'))
-
-
+
+
4.2.2 Exemple données sur les logements vacants depuis data.gouv.fr (fichier locvac produit par le CEREMA)
@@ -356,8 +361,8 @@ 4.2.2 Exemple données sur les lo
<- read_xlsx("extdata/logements-vacants-du-parc-prive-au-01012021-lovac-.xlsx", sheet = 1)
lgt_vac_prv
datatable(head(lgt_vac_prv), options = list(dom = 't'))
-
-
+
+
@@ -389,8 +394,8 @@ 4.3.1 Exemple de recours à l’A
<- fromJSON(url_urssaf_fr)
reponse_urssaf_fr <- reponse_urssaf_fr$records$fields
urssaf_fr datatable(urssaf_fr)
-
-
+
+
La récupération des métadonnées d’un jeu de données se fait avec une autre url, en voici un exemple à partir de la plateforme opendata des réseaux d’énergie (ODRE)
# Description du jeu de données
<- paste0("https://opendata.reseaux-energies.fr/api/dataset/1.0/prod-region-annuelle-enr")
@@ -836,14 +841,14 @@ dataset_url 4.6 Lire des fichiers au format p
Le package parquetize permet de convertir en masse des jeux de données depuis SAS, Stata, sqlite ou JSON vers parquet.
library(arrow)
datatable(head(iris))
-
-
+
+
<- tempfile()
tf write_parquet(iris, tf)
<- read_parquet(tf, col_select = starts_with("Se"))
df datatable(head(df))
-
-
+
+
Pour les données spatiales, le format geoparquet est désormais opérationnel (v1 en décembre 2022). Deux packages ont été développés pour l’utilisation de geoparquet avec R : {sfarrow} sur le CRAN et {geoparquet} en phase de développement actif sur github.
S’il est très efficace pour l’analyse de données, Parquet est en revanche peu adapté à l’ajout de données en continu ou à la modification fréquente de données existantes.
Pour cette utilisation, il faut privilégier un système de gestion de base de données comme par exemple PostgreSQL.
diff --git "a/manipuler-des-donn\303\251es.html" "b/manipuler-des-donn\303\251es.html"
index 0620bdf..6147b8a 100644
--- "a/manipuler-des-donn\303\251es.html"
+++ "b/manipuler-des-donn\303\251es.html"
@@ -6,7 +6,7 @@
Chapitre 5 Manipuler des données | Préparer ses données avec R et le Tidyverse
-
+
@@ -23,7 +23,7 @@
-
+
@@ -52,14 +52,15 @@
-
+
+
-
-
-
-
-
-
+
+
+
+
+
+
+
@@ -327,8 +332,8 @@ 5.4.1 Sélectionner des variables
code_reseau, code_station
)datatable(head(prelevementb))
-
-
+
+
<- select(prelevement, -code_support)
prelevementb names(prelevementb)
## [1] "code_prelevement" "code_intervenant" "code_reseau" "code_station"
@@ -415,8 +420,8 @@ 5.5.1 Manipuler des variables num
lag2x = lag(x, n = 2),
lead2x = lead(x, n = 2))
datatable(b)
-
-
+
+
opérations cumulatives ou glissantes :
@@ -431,11 +436,11 @@ 5.5.1 Manipuler des variables num
rollsumrx = roll_sumr(x, n = 2))
datatable(b)
-
-
+
+
Attention aux différences entre roll_sum()
et roll_sumr()
. Contrairement à roll_sum()
, la fonction roll_sumr()
fait en sorte d’obtenir un vecteur de même dimension que l’entrée :
$x a
-## [1] 9 5 10 6 1 7 2 3 8 4
+## [1] 3 10 6 2 8 9 5 1 7 4
<- roll_sumr(a$x, n=2)
rollsumrx <- roll_sum(a$x, n=2)
rollsumx length(rollsumrx) == length(a$x)
@@ -598,8 +603,8 @@ 5.5.4.1 Manipulations sur les car
b <- mutate(a, pos3a4 = str_sub(string = x, start = 3, end = 4),
pos3a2avtlafin = str_sub(string = x, start = 3, end = -2))
datatable(b)
-
-
+
+
str_sub()
peut être utilisé pour remplacer un caractère
str_sub(a$x, start = 6, end = 9) <-"rer"
$x a
@@ -612,8 +617,8 @@ 5.5.4.1 Manipulations sur les car
a <- data.frame(x = c(" libeatg", "delivo y"))
b <- mutate(a, y=stri_sub_replace(str=x, from=6, to=9, value = "rer"))
datatable(b)
-
-
+
+
5.5.4.2 Gestion des espaces
@@ -1070,8 +1075,8 @@ 5.10.3 filter(), mutate(), group_
across(starts_with("date"), as.Date)) %>%
head() %>%
datatable()
-
-
+
+
summarise(parametre, across(starts_with("code"), n_distinct))
## code_parametre
## 1 435
@@ -1099,8 +1104,8 @@ 5.10.3 filter(), mutate(), group_
across(ends_with("cumul12"), list(evo = ~ 100 * .x / lag (.x, 12) - 100,
part = ~ 100 *.x / log_AUT_cumul12)))
datatable(sitadel)
-
-
+
+
diff --git a/manipuler-plusieurs-tables.html b/manipuler-plusieurs-tables.html
index adfd182..6b6207c 100644
--- a/manipuler-plusieurs-tables.html
+++ b/manipuler-plusieurs-tables.html
@@ -6,7 +6,7 @@
Chapitre 6 Manipuler plusieurs tables | Préparer ses données avec R et le Tidyverse
-
+
@@ -23,7 +23,7 @@
-
+
@@ -52,14 +52,15 @@
-
+
+
-
-
-
-
-
-
+
+
+
+
+
+
+
diff --git "a/nettoyer-des-donn\303\251es-territoriales-g\303\251rer-les-\303\251volutions-du-cog-code-officiel-g\303\251ographique.html" "b/nettoyer-des-donn\303\251es-territoriales-g\303\251rer-les-\303\251volutions-du-cog-code-officiel-g\303\251ographique.html"
index 9c21900..63d0142 100644
--- "a/nettoyer-des-donn\303\251es-territoriales-g\303\251rer-les-\303\251volutions-du-cog-code-officiel-g\303\251ographique.html"
+++ "b/nettoyer-des-donn\303\251es-territoriales-g\303\251rer-les-\303\251volutions-du-cog-code-officiel-g\303\251ographique.html"
@@ -6,7 +6,7 @@
Chapitre 8 Nettoyer des données territoriales : gérer les évolutions du COG (code officiel géographique) | Préparer ses données avec R et le Tidyverse
-
+
@@ -23,7 +23,7 @@
-
+
@@ -52,14 +52,15 @@
-
+
+
-
-
-
-
-
-
+
+
+
+
+
+
+
@@ -381,7 +386,7 @@ 8.2 Mettre à jour le COG et agr
## Rows: 1,352
## Columns: 54
## $ TypeZone <fct> Epci, Epci, Epci, Epci, Epci, Epci, Epci, Epci, Epci, Epci, …
-## $ Zone <fct> "CC Faucigny-Glières", "CC du Pays de Pontchâteau St-Gildas-…
+## $ Zone <fct> "CC Faucigny - Glières", "CC du Pays de Pontchâteau St-Gilda…
## $ CodeZone <fct> 200000172, 200000438, 200000545, 200000628, 200000800, 20000…
## $ HT19 <dbl> 6, 5, 3, 11, 8, 1, 6, 9, 5, 2, 76, 6, 6, 4, 2, 1, 15, 15, 20…
## $ HT019 <dbl> 2, 2, 0, 2, 4, 1, 3, 2, 0, 1, 14, 4, 4, 0, 1, 1, 7, 5, 5, 2,…
@@ -445,7 +450,7 @@ 8.3 Sélectionner les territoires
## TypeZone Zone CodeZone HT19 HT019 HT119 HT219 HT319 HT419 HT519 HTCH19
## <fct> <fct> <fct> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 Epci CA du… 2000306… 2 0 1 0 1 0 0 61
-## 2 Epci CC de… 2000409… 9 4 0 0 4 1 0 130
+## 2 Epci CA Co… 2000409… 9 4 0 0 4 1 0 130
## 3 Epci CC de… 2000409… 3 0 0 0 3 0 0 107
## 4 Epci CC Pé… 2000419… 2 0 0 0 2 0 0 49
## 5 Epci CA de… 2000421… 5 1 0 1 2 1 0 204
diff --git a/search_index.json b/search_index.json
index a7a8e21..a9a9705 100644
--- a/search_index.json
+++ b/search_index.json
@@ -1 +1 @@
-[["index.html", "Préparer ses données avec R et le Tidyverse Chapitre 1 Introduction 1.1 Le parcours de formation 1.2 Le groupe de référents R du pôle ministériel 1.3 Objectifs du module 2", " Préparer ses données avec R et le Tidyverse Maël Theulière & Bruno Terseur 15 September 2023 Chapitre 1 Introduction Crédit photographique Sébastien Colas 1.1 Le parcours de formation Ce dispositif de formation vise à faire monter en compétence les agents du MTECT (Ministère de la Transition écologique et de la Cohésion des territoires) et du MTE (Ministère de la Transition énergétique) dans le domaine de la science de la donnée avec le logiciel R. Il est conçu pour être déployé à l’échelle nationale par le réseau des CVRH (Centre de Valorisation des Ressources Humaines). Le parcours proposé est structuré en modules de 2 jours chacun. Avoir suivi les deux premiers (ou disposer d’un niveau équivalent) est un pré-requis pour suivre les suivants qui sont proposés “à la carte” : Module 1 : Socle - Premier programme en R Module 2 : Socle - Préparation des données Module 3 : Statistiques descriptives Module 4 : Analyse des données multi-dimensionnelles Module 5 : Datavisualisation : Produire des graphiques, des cartes et des tableaux Module 6 : Publications reproductibles avec RMarkdown (à venir) Module 7 : Analyse spatiale Module 8 : Big data et optimisation du code (à venir) Module 9 : Applications interactives avec RShiny (à venir) La mise à disposition des supports de formation se fait par la page d’accueil du parcours de formation. Ces supports sont en licence ouverte. Si vous souhaitez accéder aux sources ou aux données mobilisées pendant les formations, vous pouvez directement les télécharger depuis le Github du pôle ministériel. Un package d’exercices, {savoirfR} rassemble toutes les données et les consignes d’exercices de ce parcours de formation (Modules 1, 2, 5 et 7 seulement pour l’instant). Pour vous tenir au courant de l’offre de formation proposée par le réseau des CVRH, consultez la plateforme OUPS (un accès intranet MTECT-MTE est nécessaire). Vous pouvez vous y abonner pour recevoir les annonces de formation qui vous intéressent. Pour échanger de l’information, discuter autour de R ou encore faire part de difficultés et trouver ensemble les solutions, il existe deux canaux d’entraide : s’inscrire en envoyant un message vide à l’adresse sympa@developpement-durable.gouv.fr ; rejoindre le fil Ariane #utilisateurs_r. 1.2 Le groupe de référents R du pôle ministériel Un groupe pour structurer une offre de formations sur R Un réseau d’entraide 1.3 Objectifs du module 2 Ce module va vous permettre de découvrir un ensemble de méthodes sous R afin de préparer ses données. Préparer ses données sous R, cela veut dire : Savoir les importer dans un environnement R, Mettre ses données dans de bons formats (date, catégorielle) et gérer les données manquantes, Rajouter des variables en fonction de variables existantes, Regrouper des modalités de variables, Joindre des tables entre elles pour obtenir des informations de plusieurs sources, Agréger des données, Bien définir notre table de travail en fonction des indicateurs à analyser et à leurs dimensions d’analyse. … Bref, tout le travail technique préalable entre la collecte de la donnée et sa valorisation proprement dite. On estime qu’un scientifique de la donnée passe en général la moitié de son temps à cela. Sous R, comme souvent, il y a plusieurs façons d’aborder cette question. Ce module de formation privilegie l’exploration des packages du framework tidyverse, qui ont l’avantage d’aborder les différentes phases de préparation des données d’une façon intégrée et cohérente, que ce soit entre elles, ou avec d’autres. "],["le-tidyverse.html", "Chapitre 2 Le tidyverse 2.1 Présentation des packages 2.2 Les spécificités du tidyverse 2.3 D’autres approches possibles", " Chapitre 2 Le tidyverse Le tidyverse est un ensemble de packages proposant une syntaxe cohérente pour remplir l’essentiel des traitements propres à la science de la données, de la lecture des données à la valorisation, en passant par la modélisation. Le manifeste du tidyverse comprend 4 principes clefs pour les packages : Utiliser les structures de données existantes : ne pas créer des objets ad hoc ; Utiliser l’opérateur pipe ; S’intégrer dans l’approche de programmation fonctionnelle de R ; Designé pour les être humains : favoriser la facilité d’usage à la performance machine. 2.1 Présentation des packages 2.1.1 Des packages pour lire des données 2.1.1.1 tidyverse {readr} pour les fichiers plats {readxl} pour les fichiers tableur Excel {haven} pour les données stockées sous des formats propriétaires (SAS, SPSS, …) 2.1.1.2 Hors tidyverse {odbc} / {Rposgresql} pour accéder à des données stockées sous forme de base de données {sf} pour lire des données spatiales {rsdmx} pour lire des données sdmx 2.1.2 Des packages pour manipuler des données 2.1.2.1 tidyverse {dplyr} fonctions correspondant à des “verbes” pour manipuler ses données {tidyr} fonctions pour modifier l’agencement de nos tables entre les lignes et les colonnes 2.1.3 Des packages pour nettoyer des données 2.1.3.1 tidyverse {forcats} permet de manipuler les variables de type catégoriel (ou factor en R) {stringr} permet de manipuler des chaînes de caractères {lubridate} permet de manipuler des dates 2.1.3.2 Hors tidyverse {stringi} permet de manipuler des chaînes de caractères {RcppRoll} qui regroupe des opérations fenêtrées ou glissantes 2.2 Les spécificités du tidyverse Quelques spécificités des fonctions de ce framework : Ces packages sont orientés manipulation de dataframes et non de vecteurs En conséquence, on utilise jamais l’indexation des colonnes de tables (le “$”) pour appeler une variable Chaque fonction ne fait qu’une chose et une seule (c’est une opération élémentaire) L’ensemble des fonctions obéissent à la même logique, ce qui permet de simplifier l’apprentissage L’ensemble de ces opérations élémentaires peuvent s’enchaîner à la manière d’un ETL avec le pipe 2.3 D’autres approches possibles Les fonctions que nous allons voir obéissent à une logique intégrée et simple, qui permet des manipulations complexes, à partir du moment ou l’on est capable d’identifier et de sérier chaque opération élémentaire à réaliser. D’autres packages permettent également de réaliser ce type de manipulations. La différence est qu’ils sont souvent dédiés à une tâche spécifique, ce qui rend la cohérence moins évidente lorsque l’on doit réaliser plusieurs opérations. Un autre package propose toutefois une vision intégrée de la sorte : {data.table}. Plusieurs différences sont à noter : {data.table} est plus rapide sur d’importants volumes de données, le code est très concis. {dplyr} est plus simple à apprendre, le code est plus lisible, il peut s’appliquer à des formats de données multiples, il s’intègre dans un framework global qui va de la lecture des données ({readr}, {readxl}, {haven}…) à leur valorisation ({ggplot2}). "],["bien-commencer.html", "Chapitre 3 Bien commencer 3.1 Créer un projet sous Rstudio pour vous permettre de recenser vos travaux. 3.2 Intégrer vos données 3.3 Créer votre arborescence de projet 3.4 Utilisation du package savoirfR 3.5 Activer les packages nécessaires 3.6 Bien structurer ses projets data", " Chapitre 3 Bien commencer 3.1 Créer un projet sous Rstudio pour vous permettre de recenser vos travaux. Pourquoi travailler avec les projets Rstudio plutôt que les scripts R ? Cela permet la portabilité : le répertoire de travail par défaut d’un projet est le répertoire où est ce projet. Si vous transmettez celui-ci à un collègue, le fait de lancer un programme ne dépend pas de l’arborescence de votre machine. Fini les setwd(\"chemin/qui/marche/uniquement/sur/mon/poste\") ! Toujours sur la portabilité, un projet peut être utilisé avec un outil comme renv qui va vous intégrer en interne au projet l’ensemble des packages nécessaires au projet. Cela permet donc à votre collègue à qui vous passez votre projet de ne pas avoir à les installer et, surtout, si vous mettez à jour votre environnement R, votre projet restera toujours avec les versions des packages avec lesquelles vous avez fait tourner votre projet à l’époque. Cela évite d’avoir à subir les effets d’une mise à jour importante d’un package qui casserait votre code. Pour activer renv sur un projet, il faut l’installer avec install.packages(\"renv\"). Pour intialiser la sauvegarde des packages employés dans le projet, il faut utiliser renv::init() Les packages chargés dans le projet sont enregistrés dans un sous-dossier dédié. En cours de travail sur le projet, la commande renv::snapshot() permet de faire une sauvegarde, la commande renv::restore() permet de charger la dernière sauvegarde. En savoir plus sur renv Cela permet de se forcer à travailler en mode projet : on intègre à un seul endroit tout ce qui est lié à un projet : données brutes, données retravaillées, scripts, illustrations, documentations, publications… et donc y compris les packages avec renv. On peut travailler sur plusieurs projets en même temps, Rstudio ouvre autant de sessions que de projets dans ce cas. Les projets Rstudio intègrent une interface avec les outils de gestion de version Git et SVN. Cela veut dire que vous pouvez versionner votre projet et l’héberger simplement comme répertoire sur des plateformes de gestion de code telle que Github ou Gitlab. Pour créer un projet : Cliquez sur Project en haut à droite puis New Project. Cliquez sur New Directory. 3.2 Intégrer vos données Une bonne pratique est de créer un sous répertoire /data pour stocker les données sur lesquelles vous aurez à travailler. Vous pouvez le faire depuis l’explorateur de fichiers de votre système d’exploitation ou directement à partir de l’explorateur de fichiers de RStudio. Cela marche bien quand on a un seul type de données, mais en général on va avoir à travailler sur des données brutes que l’on va retravailler ensuite et vouloir stocker à part. Si par la suite vous souhaitez avoir des exemples de bonnes pratiques sur comment structurer vos données, vous pouvez vous référer au chapitre data du livre d’Hadley Wickham sur la construction de packages R (tout package R étant aussi un projet !). 3.3 Créer votre arborescence de projet Créer un répertoire /src ou vous mettrez vos scripts R. Créer un répertoire /figures ou vous mettrez vos illustrations issues de R. 3.4 Utilisation du package savoirfR Pour faciliter le déroulé de ce module, l’ensemble des exercices (énoncés, corrigés et données) a été intégré à un package réalisé par le groupe des référents R : {savoirfR} install.packages('remotes') remotes::install_github("MTES-MCT/savoirfR") Pour l’utiliser, il suffit de créer un nouveau projet dans un nouveau répertoire, en sélectionnant le “Project Type” Exercice Parcours R MTES-MCT. Remplissez et sélectionnez le module suivi. 3.5 Activer les packages nécessaires Commencer par rajouter un script dans le répertoire /src à votre projet qui commencera par : activer l’ensemble des packages nécessaires, charger les données dont vous aurez besoin. library(tidyverse) library(lubridate) library(RcppRoll) library(DT) library(readxl) library(dbplyr) library(RPostgreSQL) library(rsdmx) library(sf) library(stringi) sitadel <- read_excel("extdata/ROES_201702.xls", sheet = "AUT_REG", col_types = c ("text","text","numeric","numeric","numeric","numeric")) load(file = "extdata/FormationPreparationDesDonnees.RData") 3.6 Bien structurer ses projets data Plusieurs documents peuvent vous inspirer sur la structuration de vos projets data par la suite. En voici quelques-uns : https://github.com/pavopax/new-project-template https://nicercode.github.io/blog/2013-04-05-projects/ https://www.inwt-statistics.com/read-blog/a-meaningful-file-structure-for-r-projects.html http://projecttemplate.net/architecture.html À partir du moment où quelques grands principes sont respectés (un répertoire pour les données brutes en lecture seule par exemple), le reste est surtout une question d’attirance plus forte pour l’une ou l’autre solution. L’important est de vous tenir ensuite à conserver toujours la même arborescence dans vos projets afin de vous y retrouver plus simplement. "],["lire-des-données.html", "Chapitre 4 Lire des données 4.1 Lire des fichiers locaux 4.2 Lire des données disponibles sur le web : téléchargement de fichiers 4.3 Lire des données disponibles sur le web via API 4.4 Lire des fichiers avec une dimension spatiale 4.5 Lire des données sous PostgreSQL 4.6 Lire des fichiers au format parquet", " Chapitre 4 Lire des données La première étape d’une chaîne de traitement est d’accéder aux données à traiter. R propose énormément de solutions pour ce faire. Quelle que soit la solution choisie, l’important est de chercher à rendre votre travail reproductible : c’est à dire reproductible dans le temps et reproductible par un collègue, sur une autre machine. L’idéal est indiquer dans le script de préparation des données comment le fichier est arrivé sur votre poste de travail, soit en codant les instructions de téléchargement, soit en ajoutant des commentaires qui vous permettront plus tard de reconstituer le jeu de données que vous utilisez. 4.1 Lire des fichiers locaux 4.1.1 {readxl} : lire des données Excel La fonction read_excel() du package {readxl} permet d’importer les données d’un fichier Excel. On peut spécifier : la feuille, les colonnes, les lignes ou la zone à importer, les lignes à supprimer avant importation, si on souhaite importer la première ligne comme des noms de variables ou non, le format des variables importées, la valeur qui sera interprétée comme étant la valeur manquante. library(readxl) sitadel <- read_excel("extdata/ROES_201702.xls", sheet = "AUT_REG", col_types = c ("text","text","numeric","numeric","numeric","numeric")) datatable(sitadel) 4.1.2 read_delim() : lire des fichiers plats La fonction read_delim() de {readr} permet d’importer les données d’un fichier csv. Elle fonctionne de la même façon que read_excel(). On peut spécifier : le caractère délimiteur de colonne, les lignes à supprimer avant importation, si on souhaite importer la première ligne comme des noms de variables ou non, le locale du fichier, la valeur qui sera interprétée comme étant la valeur manquante. read_csv(), read_csv2() et read_tsv() sont des implémentations pré-renseignées de read_delim pour lire des fichiers plats avec séparateurs , ; et tabulaire. 4.2 Lire des données disponibles sur le web : téléchargement de fichiers Parfois, les données que nous exploitons sont disponibles au téléchargement sur le web. 4.2.1 Exemple site de l’INSEE, avec dezippage Il est possible, directement depuis R, de télécharger ces données et, si nécessaire, de les décompresser (dans le répertoire de travail). Exemple sur les données 2019 de l’enquête INSEE sur les hébergements touristiques. # présentation des données sur https://www.insee.fr/fr/statistiques/2021703 url <- "https://www.insee.fr/fr/statistiques/fichier/2021703/base-cc-tourisme-2019-geo2019.zip" download.file(url, destfile = "extdata/base-cc-tourisme-2019-geo2019.zip") unzip(zipfile = "extdata/base-cc-tourisme-2019-geo2019.zip", exdir = "extdata") enq_tourisme <- read_excel("extdata/base-cc-tourisme-2019-geo2019.xls", sheet = "COM", skip = 5) datatable(head(enq_tourisme), options = list(dom = 't')) 4.2.2 Exemple données sur les logements vacants depuis data.gouv.fr (fichier locvac produit par le CEREMA) # présentation des données sur https://www.data.gouv.fr/fr/datasets/logements-vacants-du-parc-prive-par-anciennete-de-vacance-par-commune-et-par-epci/ url <- "https://www.data.gouv.fr/fr/datasets/r/ed0aa123-6afa-49fe-8e35-797a30a44c43" download.file(url, destfile = "extdata/logements-vacants-du-parc-prive-au-01012021-lovac-.xlsx", mode = "wb") lgt_vac_prv <- read_xlsx("extdata/logements-vacants-du-parc-prive-au-01012021-lovac-.xlsx", sheet = 1) datatable(head(lgt_vac_prv), options = list(dom = 't')) 4.3 Lire des données disponibles sur le web via API De plus en plus de mise à disposition de données, se font via des API (Application Programming Interface). Une API correspond à un protocole de communication entre un logiciel fournisseur et un logiciel utilisateur. L’utilisateur doit suivre une série de méthodes définies par le fournisseur. Par rapport au téléchargement de fichier via download.file(), on peut ne récupérer qu’une partie du jeu de données. L’autre avantage est la stabilité des url de téléchargement. En savoir plus sur les API : https://thinkr.fr/les-api-un-enfer/. Connaître les API de l’Etat : https://api.gouv.fr/rechercher-api Plusieurs solutions sont disponibles pour lire des données au travers d’une API dans R : tester l’API sur votre navigateur, et une fois que l’URL de requête est construite, lire le résultat JSON depuis R -> cf exemple URSSAF utiliser en complément le package {httr} qui simplifie le recours aux API dans R -> exemple ODRE utiliser un package wrapper, c’est à dire ‘enrobant’, dédié à une API spécifique, qui simplifie encore plus l’utilisation de l’API et allège l’écriture -> exemple {Didor} du ministère et {rsdmx} de l’INSEE. 4.3.1 Exemple de recours à l’API opendatasoft en utilisant l’API de l’URSSAF ou de l’ODRE Opendatasoft est une solution de plateforme opendata comprenant un catalogue, une visualisation des tables, une valorisation graphiques ou cartographiques du jeu de données diffusé et une API d’accès. Cette solution est utilisée par de nombreux acteurs publics (Urssaf, énergéticiens, collectivités, Groupe La Poste…). Chaque partie (catalogue, métadonnées, enregistrements…) fait l’objet d’une URL d’API distincte, en voici deux exemples. 1er exemple données URSSAF des effectifs salariés et de masse salariale du secteur privé par région : library(jsonlite) url_urssaf_fr <- "https://open.urssaf.fr/api/records/1.0/search/?dataset=effectifs-salaries-et-masse-salariale-du-secteur-prive-par-region-x-na38&q=&rows=10000&facet=grand_secteur_d_activite&facet=secteur_na28i&facet=annee&facet=trimestre&refine.region=Pays+de+la+Loire" reponse_urssaf_fr <- fromJSON(url_urssaf_fr) urssaf_fr <- reponse_urssaf_fr$records$fields datatable(urssaf_fr) La récupération des métadonnées d’un jeu de données se fait avec une autre url, en voici un exemple à partir de la plateforme opendata des réseaux d’énergie (ODRE) # Description du jeu de données dataset_url <- paste0("https://opendata.reseaux-energies.fr/api/dataset/1.0/prod-region-annuelle-enr") metadata <- httr::GET(dataset_url) %>% httr::content("text") %>% jsonlite::fromJSON(flatten = TRUE) attributs <- metadata$fields datatable(attributs) # Enregistrements data_url <-"https://opendata.reseaux-energies.fr/api/records/1.0/search/?dataset=prod-region-annuelle-enr&q=&rows=50&facet=code_insee_region&refine.code_insee_region=52" prod_annuelle_enr <- jsonlite::fromJSON(data_url)$records$fields 4.3.2 Packages R d’interrogation d’API Pour faciliter l’utilisation de leur API par les utilisateurs de R, certains fournisseurs propose un package R pour se brancher à leur données. Le support vous propose deux exemples (INSEE et CGDD), mais il en existe de nombreux ! Pour trouver des packages R qui facilitent l’utilisation d’API françaises, rdv sur : https://github.com/frrrenchies/frrrenchies#package-packages-package 4.3.2.1 Lire des données du webservice Insee L’Insee met à disposition un webservice d’accès (API) à des données de référence sous le format sdmx. Le package {rsdmx} permet de se connecter directement à ces données. Deux approches sont possibles. La première permet d’accéder à une série particulière. url <- "https://bdm.insee.fr/series/sdmx/data/SERIES_BDM/001564471" datainsee <- as.data.frame(readSDMX(url)) # Encoding(levels(datainsee$TITLE_FR)) <- "UTF-8" Cette approche permet également de télécharger plusieurs séries en une seule requête. Par exemple : nous téléchargeons l’ensemble des données sur les créations et défaillances d’entreprises pour les secteurs de la construction et de l’immobilier sur les Pays de la Loire. url <- "https://bdm.insee.fr/series/sdmx/data/SERIES_BDM/001564471+001564503+001564799+001564823+001582441+001582578+001582597+001582745+001656155+001656161+001655989+001655995" datainsee <- as.data.frame(readSDMX(url)) L’autre approche permet de télécharger un ensemble de données d’une thématique appelé dataflow. Ici, par exemple, on télécharge l’ensemble des données relatives à la construction neuve : url <- "https://bdm.insee.fr/series/sdmx/data/CONSTRUCTION-LOGEMENTS" datainsee <- as.data.frame(readSDMX(url)) 4.3.2.2 Interroger le catalogue DiDo du CGDD et lire les jeux de données grâce à {didor} {didor} est un package R conçu pour explorer et accéder aux données publiées par le SDES au CGDD sur DIDO. Le package {didor} s’installe depuis GitHub : install.packages("devtools") devtools::install_github("mtes-mct/didor") Voici un exemple d’utilisation pour récupérer les données de consommation de produits pétroliers dans les DROM : # devtools::install_github("mtes-mct/didor") library(didor) library(tidyverse) result <- datasets() %>% dido_search("produit-petrolier") %>% datafiles() %>% dido_search("drom") %>% get_data() knitr::kable(head(result)) Tutoriel complet : https://mtes-mct.github.io/didor/articles/premiers_pas.html 4.4 Lire des fichiers avec une dimension spatiale Le package {sf} (pour simple feature) permet d’importer dans R un fichier ayant une dimension spatiale. Après importation, le fichier est un dataframe avec une variable d’un type nouveau : la géométrie. Deux exemples ici pour lire des données au format shape et geojson. Carte_com_Mayotte <- st_read(dsn = "extdata", layer = "com_mayotte") ## Reading layer `com_mayotte' from data source ## `/__w/parcours_r_socle_preparation_des_donnees/parcours_r_socle_preparation_des_donnees/extdata' ## using driver `ESRI Shapefile' ## Simple feature collection with 17 features and 11 fields ## Geometry type: MULTIPOLYGON ## Dimension: XY ## Bounding box: xmin: 501990.5 ymin: 8562261 xmax: 532559.5 ymax: 8603052 ## Projected CRS: RGM04_UTM_zone_38S plot(Carte_com_Mayotte) communes2017 <- st_read(dsn = "extdata/communes2017.geojson") ## Reading layer `communes2017' from data source ## `/__w/parcours_r_socle_preparation_des_donnees/parcours_r_socle_preparation_des_donnees/extdata/communes2017.geojson' ## using driver `GeoJSON' ## Simple feature collection with 1281 features and 10 fields ## Geometry type: MULTIPOLYGON ## Dimension: XY ## Bounding box: xmin: 280973 ymin: 6582762 xmax: 545050 ymax: 6834665 ## Projected CRS: RGF93 / Lambert-93 plot(communes2017) Le package {sf} contient l’ensemble des fonctions permettant des manipulations sur fichiers géomatiques. On ne traitera pas ici de toutes ces fonctions en détail, se référer pour cela à la documentation du package ou suivre le module 7 du parcours de formation à R du ministère. A noter que {sf} étant complètement compatible avec les packages du tidyverse, la géométrie se conçoit comme une donnée comme une autre, sur laquelle par exemple on peut réaliser des agrégations. On peut également lire des couches directement depuis le web : st_read("https://france-geojson.gregoiredavid.fr/repo/regions.geojson") %>% filter(code > "10") %>% select(code) %>% plot() {sf} propose de lire toutes sortes de données spatiales. sf::st_drivers() ## name ## PCIDSK PCIDSK ## netCDF netCDF ## PDS4 PDS4 ## JP2OpenJPEG JP2OpenJPEG ## PDF PDF ## MBTiles MBTiles ## EEDA EEDA ## ESRI Shapefile ESRI Shapefile ## MapInfo File MapInfo File ## UK .NTF UK .NTF ## OGR_SDTS OGR_SDTS ## S57 S57 ## DGN DGN ## OGR_VRT OGR_VRT ## REC REC ## Memory Memory ## BNA BNA ## CSV CSV ## NAS NAS ## GML GML ## GPX GPX ## LIBKML LIBKML ## KML KML ## GeoJSON GeoJSON ## GeoJSONSeq GeoJSONSeq ## ESRIJSON ESRIJSON ## TopoJSON TopoJSON ## Interlis 1 Interlis 1 ## Interlis 2 Interlis 2 ## OGR_GMT OGR_GMT ## GPKG GPKG ## SQLite SQLite ## OGR_DODS OGR_DODS ## ODBC ODBC ## WAsP WAsP ## PGeo PGeo ## MSSQLSpatial MSSQLSpatial ## OGR_OGDI OGR_OGDI ## PostgreSQL PostgreSQL ## MySQL MySQL ## OpenFileGDB OpenFileGDB ## XPlane XPlane ## DXF DXF ## CAD CAD ## Geoconcept Geoconcept ## GeoRSS GeoRSS ## GPSTrackMaker GPSTrackMaker ## VFK VFK ## PGDUMP PGDUMP ## OSM OSM ## GPSBabel GPSBabel ## SUA SUA ## OpenAir OpenAir ## OGR_PDS OGR_PDS ## WFS WFS ## WFS3 WFS3 ## SOSI SOSI ## HTF HTF ## AeronavFAA AeronavFAA ## Geomedia Geomedia ## EDIGEO EDIGEO ## GFT GFT ## SVG SVG ## CouchDB CouchDB ## Cloudant Cloudant ## Idrisi Idrisi ## ARCGEN ARCGEN ## SEGUKOOA SEGUKOOA ## SEGY SEGY ## XLS XLS ## ODS ODS ## XLSX XLSX ## ElasticSearch ElasticSearch ## Walk Walk ## Carto Carto ## AmigoCloud AmigoCloud ## SXF SXF ## Selafin Selafin ## JML JML ## PLSCENES PLSCENES ## CSW CSW ## VDV VDV ## GMLAS GMLAS ## MVT MVT ## TIGER TIGER ## AVCBin AVCBin ## AVCE00 AVCE00 ## NGW NGW ## HTTP HTTP ## long_name ## PCIDSK PCIDSK Database File ## netCDF Network Common Data Format ## PDS4 NASA Planetary Data System 4 ## JP2OpenJPEG JPEG-2000 driver based on OpenJPEG library ## PDF Geospatial PDF ## MBTiles MBTiles ## EEDA Earth Engine Data API ## ESRI Shapefile ESRI Shapefile ## MapInfo File MapInfo File ## UK .NTF UK .NTF ## OGR_SDTS SDTS ## S57 IHO S-57 (ENC) ## DGN Microstation DGN ## OGR_VRT VRT - Virtual Datasource ## REC EPIInfo .REC ## Memory Memory ## BNA Atlas BNA ## CSV Comma Separated Value (.csv) ## NAS NAS - ALKIS ## GML Geography Markup Language (GML) ## GPX GPX ## LIBKML Keyhole Markup Language (LIBKML) ## KML Keyhole Markup Language (KML) ## GeoJSON GeoJSON ## GeoJSONSeq GeoJSON Sequence ## ESRIJSON ESRIJSON ## TopoJSON TopoJSON ## Interlis 1 Interlis 1 ## Interlis 2 Interlis 2 ## OGR_GMT GMT ASCII Vectors (.gmt) ## GPKG GeoPackage ## SQLite SQLite / Spatialite ## OGR_DODS OGR_DODS ## ODBC ODBC ## WAsP WAsP .map format ## PGeo ESRI Personal GeoDatabase ## MSSQLSpatial Microsoft SQL Server Spatial Database ## OGR_OGDI OGDI Vectors (VPF, VMAP, DCW) ## PostgreSQL PostgreSQL/PostGIS ## MySQL MySQL ## OpenFileGDB ESRI FileGDB ## XPlane X-Plane/Flightgear aeronautical data ## DXF AutoCAD DXF ## CAD AutoCAD Driver ## Geoconcept Geoconcept ## GeoRSS GeoRSS ## GPSTrackMaker GPSTrackMaker ## VFK Czech Cadastral Exchange Data Format ## PGDUMP PostgreSQL SQL dump ## OSM OpenStreetMap XML and PBF ## GPSBabel GPSBabel ## SUA Tim Newport-Peace's Special Use Airspace Format ## OpenAir OpenAir ## OGR_PDS Planetary Data Systems TABLE ## WFS OGC WFS (Web Feature Service) ## WFS3 OGC WFS 3 client (Web Feature Service) ## SOSI Norwegian SOSI Standard ## HTF Hydrographic Transfer Vector ## AeronavFAA Aeronav FAA ## Geomedia Geomedia .mdb ## EDIGEO French EDIGEO exchange format ## GFT Google Fusion Tables ## SVG Scalable Vector Graphics ## CouchDB CouchDB / GeoCouch ## Cloudant Cloudant / CouchDB ## Idrisi Idrisi Vector (.vct) ## ARCGEN Arc/Info Generate ## SEGUKOOA SEG-P1 / UKOOA P1/90 ## SEGY SEG-Y ## XLS MS Excel format ## ODS Open Document/ LibreOffice / OpenOffice Spreadsheet ## XLSX MS Office Open XML spreadsheet ## ElasticSearch Elastic Search ## Walk Walk ## Carto Carto ## AmigoCloud AmigoCloud ## SXF Storage and eXchange Format ## Selafin Selafin ## JML OpenJUMP JML ## PLSCENES Planet Labs Scenes API ## CSW OGC CSW (Catalog Service for the Web) ## VDV VDV-451/VDV-452/INTREST Data Format ## GMLAS Geography Markup Language (GML) driven by application schemas ## MVT Mapbox Vector Tiles ## TIGER U.S. Census TIGER/Line ## AVCBin Arc/Info Binary Coverage ## AVCE00 Arc/Info E00 (ASCII) Coverage ## NGW NextGIS Web ## HTTP HTTP Fetching Wrapper ## write copy is_raster is_vector vsi ## PCIDSK TRUE FALSE TRUE TRUE TRUE ## netCDF TRUE TRUE TRUE TRUE TRUE ## PDS4 TRUE TRUE TRUE TRUE TRUE ## JP2OpenJPEG FALSE TRUE TRUE TRUE TRUE ## PDF TRUE TRUE TRUE TRUE TRUE ## MBTiles TRUE TRUE TRUE TRUE TRUE ## EEDA FALSE FALSE FALSE TRUE FALSE ## ESRI Shapefile TRUE FALSE FALSE TRUE TRUE ## MapInfo File TRUE FALSE FALSE TRUE TRUE ## UK .NTF FALSE FALSE FALSE TRUE TRUE ## OGR_SDTS FALSE FALSE FALSE TRUE TRUE ## S57 TRUE FALSE FALSE TRUE TRUE ## DGN TRUE FALSE FALSE TRUE TRUE ## OGR_VRT FALSE FALSE FALSE TRUE TRUE ## REC FALSE FALSE FALSE TRUE FALSE ## Memory TRUE FALSE FALSE TRUE FALSE ## BNA TRUE FALSE FALSE TRUE TRUE ## CSV TRUE FALSE FALSE TRUE TRUE ## NAS FALSE FALSE FALSE TRUE TRUE ## GML TRUE FALSE FALSE TRUE TRUE ## GPX TRUE FALSE FALSE TRUE TRUE ## LIBKML TRUE FALSE FALSE TRUE TRUE ## KML TRUE FALSE FALSE TRUE TRUE ## GeoJSON TRUE FALSE FALSE TRUE TRUE ## GeoJSONSeq TRUE FALSE FALSE TRUE TRUE ## ESRIJSON FALSE FALSE FALSE TRUE TRUE ## TopoJSON FALSE FALSE FALSE TRUE TRUE ## Interlis 1 TRUE FALSE FALSE TRUE TRUE ## Interlis 2 TRUE FALSE FALSE TRUE TRUE ## OGR_GMT TRUE FALSE FALSE TRUE TRUE ## GPKG TRUE TRUE TRUE TRUE TRUE ## SQLite TRUE FALSE FALSE TRUE TRUE ## OGR_DODS FALSE FALSE FALSE TRUE FALSE ## ODBC TRUE FALSE FALSE TRUE FALSE ## WAsP TRUE FALSE FALSE TRUE TRUE ## PGeo FALSE FALSE FALSE TRUE FALSE ## MSSQLSpatial TRUE FALSE FALSE TRUE FALSE ## OGR_OGDI FALSE FALSE FALSE TRUE FALSE ## PostgreSQL TRUE FALSE FALSE TRUE FALSE ## MySQL TRUE FALSE FALSE TRUE FALSE ## OpenFileGDB FALSE FALSE FALSE TRUE TRUE ## XPlane FALSE FALSE FALSE TRUE TRUE ## DXF TRUE FALSE FALSE TRUE TRUE ## CAD FALSE FALSE TRUE TRUE TRUE ## Geoconcept TRUE FALSE FALSE TRUE TRUE ## GeoRSS TRUE FALSE FALSE TRUE TRUE ## GPSTrackMaker TRUE FALSE FALSE TRUE TRUE ## VFK FALSE FALSE FALSE TRUE FALSE ## PGDUMP TRUE FALSE FALSE TRUE TRUE ## OSM FALSE FALSE FALSE TRUE TRUE ## GPSBabel TRUE FALSE FALSE TRUE FALSE ## SUA FALSE FALSE FALSE TRUE TRUE ## OpenAir FALSE FALSE FALSE TRUE TRUE ## OGR_PDS FALSE FALSE FALSE TRUE TRUE ## WFS FALSE FALSE FALSE TRUE TRUE ## WFS3 FALSE FALSE FALSE TRUE FALSE ## SOSI FALSE FALSE FALSE TRUE FALSE ## HTF FALSE FALSE FALSE TRUE TRUE ## AeronavFAA FALSE FALSE FALSE TRUE TRUE ## Geomedia FALSE FALSE FALSE TRUE FALSE ## EDIGEO FALSE FALSE FALSE TRUE TRUE ## GFT TRUE FALSE FALSE TRUE FALSE ## SVG FALSE FALSE FALSE TRUE TRUE ## CouchDB TRUE FALSE FALSE TRUE FALSE ## Cloudant TRUE FALSE FALSE TRUE FALSE ## Idrisi FALSE FALSE FALSE TRUE TRUE ## ARCGEN FALSE FALSE FALSE TRUE TRUE ## SEGUKOOA FALSE FALSE FALSE TRUE TRUE ## SEGY FALSE FALSE FALSE TRUE TRUE ## XLS FALSE FALSE FALSE TRUE FALSE ## ODS TRUE FALSE FALSE TRUE TRUE ## XLSX TRUE FALSE FALSE TRUE TRUE ## ElasticSearch TRUE FALSE FALSE TRUE FALSE ## Walk FALSE FALSE FALSE TRUE FALSE ## Carto TRUE FALSE FALSE TRUE FALSE ## AmigoCloud TRUE FALSE FALSE TRUE FALSE ## SXF FALSE FALSE FALSE TRUE TRUE ## Selafin TRUE FALSE FALSE TRUE TRUE ## JML TRUE FALSE FALSE TRUE TRUE ## PLSCENES FALSE FALSE TRUE TRUE FALSE ## CSW FALSE FALSE FALSE TRUE FALSE ## VDV TRUE FALSE FALSE TRUE TRUE ## GMLAS FALSE TRUE FALSE TRUE TRUE ## MVT TRUE FALSE FALSE TRUE TRUE ## TIGER TRUE FALSE FALSE TRUE TRUE ## AVCBin FALSE FALSE FALSE TRUE TRUE ## AVCE00 FALSE FALSE FALSE TRUE TRUE ## NGW TRUE TRUE TRUE TRUE FALSE ## HTTP FALSE FALSE TRUE TRUE FALSE Il comprend notamment un driver pour lire les flux WFS, émis par nos plateforme de données géographiques. Voici un exemple issu de SIGloire : crte <- sf::st_read(dsn = 'https://datacarto.sigloire.fr/wfs?REQUEST=getCapabilities&service=WFS&VERSION=2.0.0', layer = "ms:r_portrait_crte_r52") crte %>% select(nom_territ) %>% plot On indique au niveau du paramètre dsn l’url du webservice WFS de la plateforme et au niveau du parametre layer le nom de la couche. Pour aller plus loin dans l’exploitation des flux WFS dans R : https://inbo.github.io/tutorials/tutorials/spatial_wfs_services/. 4.5 Lire des données sous PostgreSQL Deux approches possibles pour utiliser des données stockées dans une base de données PostgreSQL. Importer toutes ces données dans l’environnement R se connecter à ces données (sans les charger en mémoire vive) et utiliser un interpréteur permettant de traduire du code R comme une requête SQL. 4.5.1 Lire des données sous PostgreSQL : première approche Le package {DBI} est fréquemment utilisé pour connecter des bases de données à R. On ouvre une connexion en déclarant les informations liées à la base (adresse, identifiants..) et en choisissant le driver de connexion. #Définition du driver drv <- dbDriver("PostgreSQL") #Définition de la base de données con <- dbConnect(drv, dbname = "dbname", host = "ip", port = numero_du_port, user = "user_name", password = "pwd") #Spécification de l'encodage, obligatoire avec Windows postgresqlpqExec(con, "SET client_encoding = 'windows-1252'") #Téléchargement de la table analyse du schéma pesticide parametre <- dbGetQuery(con, "SELECT * FROM pesticides.parametre") #Téléchargement de données avec dimension spatiale via la fonction st_read du package simple feature station = st_read(con, query = "SELECT * FROM pesticides.station") station = st_read(dsn = con, layer = c(schema = 'pesticides', table = 'station')) On voit que pour importer notre table analyse, on a simplement lancé une requête SQL. Pour obtenir un résultat qui préserve le caractère spatial de notre jeu de données, il faut changer de fonction de lecture. Un package, encore expérimental, de la DREAL Pays de la Loire, {datalibaba} simplifie l’écriture des instructions de lecture/écriture de données vers ou depuis un SGBD Postgresql/postgis. Il propose de stocker vos identifiants de connexion dans vos variable d’environnement afin d’en préserver la confidentialité et de vous éviter de les réécrire dans chaque script. L’utilisateur n’a plus à se préoccuper du driver de connexion ni de la fonction de lecture. Les instruction précédentes deviennent : remotes::install_gitlab('dreal-datalab/datalibaba') library(datalibaba) parametre <- importer_data(table = "parametre", schema = "pesticides") station <- importer_data(table = "station", schema = "pesticides") 4.5.2 Lire des données sous PostgreSQL : seconde approche #définition du driver drv <- dbDriver("PostgreSQL") #définition de la base de données con <- dbConnect(drv, dbname = "dbname", host = "ip", port = numero_du_port, user = "user_name", password = "pwd") #spécification de l'encodage, obligatoire avec windows postgresqlpqExec(con, "SET client_encoding = 'windows-1252'") #téléchargement de la table analyse du schéma pesticide analyse_db <- tbl(con, in_schema("pesticides", "analyse")) Ici la table analyse n’est pas chargée dans l’environnement R, R s’est juste connecté à la base de données. On peut réaliser des opérations sur la table analyse avec du code R très simplement. Par exemple pour filtrer sur les analyses relatives au Glyphosate : analyse_db <- filter(analyse_db, code_parametre == 1506) Attention, ce code ne touche pas la base de donnée, il n’est pas exécuté. Pour l’exécuter, il faut par exemple afficher la table. analyse_db Même une fois le code exécuté, cette base n’est pas encore un dataframe. Pour importer la table, on utilise la fonction collect() analyse_db <- collect(analyse_db) Cette approche est à conseiller sur d’importantes bases de données, et sans dimension spatiale, car {dbplyr} ne sait pas encore lire facilement ce type de variable. 4.6 Lire des fichiers au format parquet Apache Parquet est un choix de plus en plus populaire pour le stockage et l’analyse de données. C’est un format binaire optimisé pour réduire la taille des fichiers et offrir une excellente vitesse de lecture, surtout si on souhaite accéder à un jeu de données en ne lisant que quelques colonnes. Egalement, il est lisible dans de nombreux langages et prévoit, un peu comme avec une base de données PostgreSQL, qu’on exprime une requête de lecture pour limiter la montée des données en RAM au minimum nécessaire. Enfin on peut grouper les lignes lors un export parquet et réaliser une partition du fichier, par exemple par département ou par région, dans l’idée que certains utilisateurs n’ont pas besoin d’accéder à tout, pour encore accélérer la lecture. Bref, cela va devenir un must dans la diffusion de données millésimées. La manière la plus courante de lire et d’écrire des données au format Parquet avec R est d’utiliser le package {Arrow}, et ses les fonctions read_parquet() et write_parquet(). Le package parquetize permet de convertir en masse des jeux de données depuis SAS, Stata, sqlite ou JSON vers parquet. library(arrow) datatable(head(iris)) tf <- tempfile() write_parquet(iris, tf) df <- read_parquet(tf, col_select = starts_with("Se")) datatable(head(df)) Pour les données spatiales, le format geoparquet est désormais opérationnel (v1 en décembre 2022). Deux packages ont été développés pour l’utilisation de geoparquet avec R : {sfarrow} sur le CRAN et {geoparquet} en phase de développement actif sur github. S’il est très efficace pour l’analyse de données, Parquet est en revanche peu adapté à l’ajout de données en continu ou à la modification fréquente de données existantes. Pour cette utilisation, il faut privilégier un système de gestion de base de données comme par exemple PostgreSQL. Pour en savoir plus sur ce format promis à un bel avenir au ministère : nous vous recommandons la fiche utilitR de l’INSEE dédiée à la question. "],["manipuler-des-données.html", "Chapitre 5 Manipuler des données 5.1 Les principes des fonctions de {dplyr} 5.2 Présentation des données 5.3 Chargement des données 5.4 Les verbes clefs de {dplyr} pour manipuler une table 5.5 La boîte à outils pour créer et modifier des variables avec R 5.6 Agréger des données : summarise() 5.7 Agréger des données par dimension : group_by() 5.8 Le pipe 5.9 La magie des opérations groupées 5.10 Les armes non conventionnelles de la préparation des donnéees", " Chapitre 5 Manipuler des données 5.1 Les principes des fonctions de {dplyr} Le but de {dplyr} est d’identifier et de rassembler dans un seul package les outils de manipulation de données les plus importantes pour l’analyse des données. Ce package rassemble donc des fonctions correspondant à un ensemble d’opérations élémentaires (ou verbes) qui permettent de : Sélectionner un ensemble de variables : select() Sélectionner un ensemble de lignes : filter() Ajouter/modifier/renommer des variables : mutate() ou rename() Produire des statistiques agrégées sur les dimensions d’une table : summarise() Trier une table : arrange() Manipuler plusieurs tables : left_join(), right_join(), full_join(), inner_join()… D’appliquer cela sur des données, quel que soit leur format : dataframes, data.table, couche spatiale, base de données sql, big data… D’appliquer cela en articulation avec group_by() qui change la façon d’interpréter chaque fonction : d’une interprétation globale sur l’ensemble d’une table, on passe alors à une approche groupe par groupe : chaque groupe étant défini par un ensemble des modalités des variables définies dans l’instruction group_by(). 5.2 Présentation des données On va travailler sur ce module principalement à partir des données sitadel en date réelle estimée (permis de construire) et à partir des données de qualité des eaux de surface. 5.3 Chargement des données load(file = "extdata/FormationPreparationDesDonnees.RData") 5.4 Les verbes clefs de {dplyr} pour manipuler une table 5.4.1 Sélectionner des variables : select() Nous allons ici sélectionner un ensemble de variables de la table des prélèvements. prelevementb <- select( prelevement, date_prelevement, code_prelevement, code_reseau, code_station ) datatable(head(prelevementb)) prelevementb <- select(prelevement, -code_support) names(prelevementb) ## [1] "code_prelevement" "code_intervenant" "code_reseau" "code_station" ## [5] "date_prelevement" select() possède ce qu’on appelle des helpers qui permettent de gagner du temps dans l’écriture de notre sélection. A partir du moment où les conventions de nommage sont correctement effectuées, cela permet de gagner également en reproductibilité d’une année sur l’autre. Exemple : sélectionner toutes les variables qui commencent par “code_” : prelevementb <- select(prelevement, starts_with("code_")) Exemple : sélectionner les variables dont les noms sont contenus dans un vecteur de chaînes de caractères : mes_variables <- c("code_prelevement", "code_intervenant", "code_reseau", "date_prelevement") prelevementb <- select(prelevement, one_of(mes_variables)) 5.4.2 Trier une table : arrange() prelevementb <- arrange(prelevementb, date_prelevement) 5.4.3 Renommer une variable : rename() prelevementb <- rename(prelevementb, date_p = date_prelevement) On peut aussi directement renommer une variable dans l’opération select() prelevementb <- select(prelevement, date_p = date_prelevement, code_prelevement, code_reseau, code_station) 5.4.4 Filtrer une table : filter() On va ici récupérer les analyses produites par l’ARS ars <- filter(prelevement, code_reseau == "ARS") L’exemple ci-dessus n’exerce un filtre que sur une condition unique. Pour des conditions cumulatives (toutes les conditions doivent être remplies), le \"&\" ou la \",\" ars <- filter(prelevement, code_reseau == "ARS", code_intervenant == "44") Pour des conditions non cumulatives (au moins une des conditions doit être remplie), le “|” ars <- filter(prelevement, code_reseau == "ARS" | code_reseau == "FREDON") Si une condition non cumulative s’applique sur une même variable, privilégier un test de sélection dans une liste avec le %in% ars <- filter(prelevement, code_reseau %in% c("ARS", "FREDON")) Pour sélectionner des observations qui ne répondent pas à la condition, le ! (la négation d’un test) Toutes les observations ayant été réalisées par un autre réseau que l’ARS : non_ars <- filter(prelevement, code_reseau != "ARS") Toutes les observations ayant été réalisées par un autre réseau que l’ARS ou FREDON : ni_ars_ni_fredon <- filter(prelevement, !(code_reseau %in% c("ARS", "FREDON"))) 5.4.5 Modifier/ajouter une variable : mutate() mutate() est le verbe qui permet la transformation d’une variable existante ou la création d’une nouvelle variable dans le jeu de données. Création de nouvelles variables : prelevementb <- mutate(prelevementb, code_prelevement_caract = as.character(code_prelevement), code_reseau_fact = as.factor(code_reseau) ) Modification de variables existantes : prelevementb <- mutate(prelevementb, code_prelevement = as.character(code_prelevement), code_reseau = as.factor(code_reseau) ) mutate() possède une variante, transmute(), qui fonctionne de la même façon, mais ne conserve que les variables modifiées ou créées par le verbe. 5.4.6 Extraire un vecteur : pull() pull() permet d’extraire sous forme de vecteur une variable d’un dataframe. stations_de_la_table_prelevement <- pull(prelevement, code_station) stations_de_la_table_prelevement <- unique(stations_de_la_table_prelevement) 5.5 La boîte à outils pour créer et modifier des variables avec R 5.5.1 Manipuler des variables numériques Vous pouvez utiliser beaucoup de fonctions pour créer des variables avec mutate() : les opérations arithmétiques : +,-,*,/,^ ; arithmétique modulaire : %/% (division entière) et %% (le reste), où x == y * (x %/% y) + (x %% y) ; logarithmes : log(), log2(), log10() ; navigations entre les lignes : lead() et lag() qui permettent d’avoir accès à la valeur suivante et précédente d’une variable. a <- data.frame(x=sample(1:10)) b <- mutate(a, lagx = lag(x), leadx = lead(x), lag2x = lag(x, n = 2), lead2x = lead(x, n = 2)) datatable(b) opérations cumulatives ou glissantes : R fournit des fonctions pour obtenir des opérations cumulatives les somme, produit, minimum et maximum cumulés, dplyr fournit l’équivalent pour les moyennes : cumsum(), cumprod(), cummin(), cummax(), cummean() Pour appliquer des opérations glissantes, on peut soit créer l’opération avec l’instruction lag(), soit exploiter le package RcppRoll qui permet d’exploiter des fonctions prédéfinies. Exemple de somme glissante sur un pas de 2 observations. a <- data.frame(x = sample(1:10)) b <- mutate(a, cumsumx = cumsum(x), rollsumrx = roll_sumr(x, n = 2)) datatable(b) Attention aux différences entre roll_sum() et roll_sumr(). Contrairement à roll_sum(), la fonction roll_sumr() fait en sorte d’obtenir un vecteur de même dimension que l’entrée : a$x ## [1] 9 5 10 6 1 7 2 3 8 4 rollsumrx <- roll_sumr(a$x, n=2) rollsumx <- roll_sum(a$x, n=2) length(rollsumrx) == length(a$x) ## [1] TRUE length(rollsumx) == length(a$x) ## [1] FALSE Aussi dans le cadre d’opérations sur les dataframes, roll_sum() ne fonctionnera pas. b <- mutate(a, cumsumx = cumsum(x), rollsumx = roll_sum(x, n=2)) Comparaisons logiques : <, <=, >, >=, != Rangs : min_rank() devrait être la plus utile, il existe aussi notamment row_number(), dense_rank(), percent_rank(), cume_dist(), ntile(). coalesce(x, y) : permet de remplacer les valeurs manquantes de x par celle de y variable = ifelse(condition(x), valeursioui, valeursinon) permet d’affecter valeursi ou valeursinon à variable en fonction du fait que x répond à condition. Exemple : création d’une variable résultat pour savoir si les résultats de nos analyses sont bons, ou non. analyseb <- mutate(analyse, resultat_ok = ifelse(code_remarque %in% c(1, 2, 7, 10), yes = TRUE, no = FALSE)) qui peut se résumer, lorsque yes = TRUE et no = FALSE, à : analyseb <- mutate(analyse, resultat_ok = code_remarque %in% c(1, 2, 7, 10)) case_when() permet d’étendre la logique de ifelse() à des cas plus complexes. Les conditions mises dans un case_when() ne sont pas exclusives. De ce fait, il faut pouvoir déterminer l’ordre d’évaluation des conditions qui y sont posées. Cet ordre s’effectue de bas en haut, c’est à dire que la dernière condition évaluée (celle qui primera sur toutes les autres) sera la première à écrire. Exemple: On va ici calculer des seuils fictifs sur les analyses. analyseb <- mutate(analyse, classe_resultat_analyse = case_when( resultat_analyse == 0 ~ "1", resultat_analyse <= 0.001 ~ "2", resultat_analyse <= 0.01 ~ "3", resultat_analyse <= 0.1 ~ "4", resultat_analyse > 0.1 ~ "5", TRUE ~ "" )) 5.5.2 Exercice 1 : Les données mensuelles sitadel cf. package d’exercices {savoirfR} À partir du fichier sitadel de février 2017 (ROES_201702.xls), produire un dataframe ‘sit_pdl_ind’ contenant pour la région Pays-de-la-Loire (code région 52), pour chaque mois et pour les logements individuels (définis par la somme des logements individuels purs et individuels groupés : i_AUT = ip_AUT + ig_AUT) : le cumul des autorisations sur 12 mois glissants (i_AUT_cum12), le taux d’évolution du cumul sur 12 mois (i_AUT_cum_evo, en %), la part de ce cumul dans celui de l’ensemble des logements autorisés (log_AUT), en pourcentage. Résultat attendu : solution sans le pipe (apercu des premières lignes) %>% ## # A tibble: 6 × 12 ## date REG log_AUT ip_AUT ig_AUT colres_AUT i_AUT i_AUT_cum12 ## <chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> ## 1 200001 52 1789 1266 245 278 1511 NA ## 2 200002 52 2022 1529 175 318 1704 NA ## 3 200003 52 2270 1466 205 599 1671 NA ## 4 200004 52 2040 1237 162 641 1399 NA ## 5 200005 52 2361 1357 357 647 1714 NA ## 6 200006 52 2504 1436 250 818 1686 NA ## # ℹ 4 more variables: i_AUT_cum12_lag12 <dbl>, i_AUT_cum_evo <dbl>, ## # log_AUT_cum12 <dbl>, part_i_AU <dbl> solution avec le pipe (apercu des premières lignes) %>% ## # A tibble: 6 × 12 ## date REG log_AUT ip_AUT ig_AUT colres_AUT i_AUT i_AUT_cum12 ## <chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> ## 1 200001 52 1789 1266 245 278 1511 NA ## 2 200002 52 2022 1529 175 318 1704 NA ## 3 200003 52 2270 1466 205 599 1671 NA ## 4 200004 52 2040 1237 162 641 1399 NA ## 5 200005 52 2361 1357 357 647 1714 NA ## 6 200006 52 2504 1436 250 818 1686 NA ## # ℹ 4 more variables: i_AUT_cum12_lag12 <dbl>, i_AUT_cum_evo <dbl>, ## # log_AUT_cum12 <dbl>, part_i_AU <dbl> 5.5.3 Manipuler des dates Parmi l’ensemble des manipulations de variables, celle des dates et des heures est toujours une affaire complexe. Le framework tidyverse propose le package {lubridate} qui permet de gérer ces informations de façon cohérente. gestion des dates : dmy("jeudi 21 novembre 2020") dmy("21112020") ymd("20201121") gestion des dates/heures : dmy_hms("mardi 21 novembre 2020 9:30:00") now() combien de jours avant Noël ? annee_en_cours <- year(today()) prochain_noel <- paste("25 décembre", annee_en_cours) prochain_noel dmy(prochain_noel) - today() le jour de la semaine d’une date : wday(dmy("19012038"), label = TRUE) Les fonctions make_date() et make_datetime() vous permettent de transformer un ensemble de variables en un format date ou date - heure. C’est par exemple utile lorsque l’on a des variables séparées pour l’année, le mois et le jour. 5.5.3.1 Exercice 2 : les dates Convertir les colonnes de la table exercice au format date (quand c’est pertinent). La table exercice est issue de FormationPreparationDesDonnees.RData. Résultat attendu : ## Rows: 153,497 ## Columns: 22 ## $ code_analyse <int> 5186581, 280131, 1576225, 799894, 472800, 27671… ## $ code_laboratoire <dbl> NA, 292, NA, NA, 292, NA, NA, NA, NA, NA, NA, N… ## $ code_prelevement <int> 37593, 7715, 15517, 9566, 8332, 26792, 35625, 1… ## $ code_parametre <dbl> 1216, 1668, 1185, 1217, 1907, 1945, 1673, 1234,… ## $ code_fraction_analysee <int> 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,… ## $ resultat_analyse <dbl> 0.007, 0.050, 0.040, 0.050, 0.260, 0.020, 0.010… ## $ code_remarque <int> 10, 2, 2, 2, 1, 10, 10, 10, 10, 10, 10, 10, 2, … ## $ limite_detection <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,… ## $ limite_quantification <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,… ## $ code_intervenant <fct> NA, 104, NA, NA, 104, NA, NA, 53, NA, 44, 49, 4… ## $ code_reseau <fct> OSUR, OSUR, FREDON, OSUR, OSUR, OSUR, OSUR, ARS… ## $ code_station <chr> "04153800", "04130000", "04132500", "04214000",… ## $ date_prelevement <date> 2014-09-16, 2003-08-05, 2008-09-01, 2007-05-02… ## $ code_support <int> NA, 3, NA, NA, 3, NA, NA, 3, NA, 3, 3, 3, NA, N… ## $ libelle_station <chr> "MOZEE à CHANTONNAY", "MAYENNE à DAON", "MAYENN… ## $ date_creation <date> 1900-01-01, 1900-01-01, 1900-01-01, 1900-01-01… ## $ source <chr> "AELB", "AELB", "AELB", "AELB", "AELB", "AELB",… ## $ code_masse_eau <chr> "GR1950", "GR0460c", "GR0460c", "GR0121", "GR04… ## $ code_entite_hydro <chr> "N3036200", "M---0090", "M---0090", "J78-0300",… ## $ code_troncon_hydro <chr> "N3036200", "M3620090", "M3910090", "J7800300",… ## $ code_commune <chr> "85051", "53089", "49214", "44036", "53017", "5… ## $ date_formatee <chr> "16/09/2014", "05/08/2003", "01/09/2008", "02/0… 5.5.4 Manipuler des chaînes de caractères Le package {stringr} compile l’ensemble des fonctions de manipulation de chaînes de caractère utiles sur ce type de données. On peut diviser les manipulations de chaînes de caractères en 4 catégories : manipulations des caractères eux-mêmes, gestion des espaces, opérations liées à la langue, manipulations de “pattern”, notamment des expressions régulières. 5.5.4.1 Manipulations sur les caractères Obtenir la longueur d’une chaîne avec str_length() : library(stringr) str_length("abc") ## [1] 3 Extraire une chaîne de caractères avec str_sub() str_sub() prend 3 arguments : une chaîne de caractère, une position de début, une position de fin. Les positions peuvent être positives, et dans ce cas, on compte à partir de la gauche, ou négatives, et dans ce cas on compte à partir de la droite. a <- data.frame(x = c(" libeatg", "delivo y")) b <- mutate(a, pos3a4 = str_sub(string = x, start = 3, end = 4), pos3a2avtlafin = str_sub(string = x, start = 3, end = -2)) datatable(b) str_sub() peut être utilisé pour remplacer un caractère str_sub(a$x, start = 6, end = 9) <-"rer" a$x ## [1] " liberer" "delivrer" Si on souhaite réaliser ce genre d’opération dans le cadre d’un mutate, il faut utiliser une fonction dite “pipe-operator-friendly”, par exemple stri_sub_replace() du package {stringi} # install.packages("stringi") library(stringi) a <- data.frame(x = c(" libeatg", "delivo y")) b <- mutate(a, y=stri_sub_replace(str=x, from=6, to=9, value = "rer")) datatable(b) 5.5.4.2 Gestion des espaces La fonction str_pad() permet de compléter une chaîne de caractère pour qu’elle atteigne une taille fixe. Le cas typique d’usage est la gestion des codes communes Insee. code_insee <- 1001 str_pad(code_insee, 5, pad = "0") ## [1] "01001" On peut choisir de compléter à gauche, à droite, et on peut choisir le “pad”. Par défaut, celui-ci est l’espace. La fonction inverse de str_pad() est str_trim() qui permet de supprimer les espaces aux extrémités de notre chaîne de caractères. proust <- " Les paradoxes d'aujourd'hui sont les préjugés de demain. " str_trim(proust) ## [1] "Les paradoxes d'aujourd'hui sont les préjugés de demain." str_trim(proust, side = "left") ## [1] "Les paradoxes d'aujourd'hui sont les préjugés de demain. " Les expressions régulières permettent la détection de “patterns” sur des chaînes de caractères. Par exemple “^” sert à indiquer que la chaîne de caractère recherchée doit se trouver au début de la chaîne examinée. Au contraire, “$” sert à indiquer que la chaîne de caractère recherchée doit se trouver à la fin. a <- data.frame(txt = c("vélo", "train", "voilier", "bus", "avion", "tram", "trottinette")) b <- mutate(a, tr_au_debut = str_detect(string = txt, pattern = "^tr")) b ## txt tr_au_debut ## 1 vélo FALSE ## 2 train TRUE ## 3 voilier FALSE ## 4 bus FALSE ## 5 avion FALSE ## 6 tram TRUE ## 7 trottinette TRUE filter(b, tr_au_debut) ## txt tr_au_debut ## 1 train TRUE ## 2 tram TRUE ## 3 trottinette TRUE filter(a, str_detect(string = txt, pattern = "n$")) ## txt ## 1 train ## 2 avion 5.5.4.3 Opérations liées à la langue Ces différentes fonctions ne donneront pas le même résultat en fonction de la langue par défaut utilisée. La gestion des majuscules/minuscules : proust <- "Les paradoxes d'aujourd'hui sont LES préjugés de Demain." str_to_upper(proust) ## [1] "LES PARADOXES D'AUJOURD'HUI SONT LES PRÉJUGÉS DE DEMAIN." str_to_lower(proust) ## [1] "les paradoxes d'aujourd'hui sont les préjugés de demain." str_to_title(proust) ## [1] "Les Paradoxes D'aujourd'hui Sont Les Préjugés De Demain." La gestion de l’ordre, str_sort() et str_order() : a <- data.frame(x = c("y", "i", "k")) mutate(a, en_ordre = str_sort(x), selon_position = str_order(x)) ## x en_ordre selon_position ## 1 y i 2 ## 2 i k 3 ## 3 k y 1 Suppression des accents (base::iconv) : proust2 <- "Les paradoxes d'aujourd'hui sont les préjugés de demain ; et ça c'est embêtant" iconv(proust2, to = "ASCII//TRANSLIT") ## [1] "Les paradoxes d'aujourd'hui sont les prejuges de demain ; et ca c'est embetant" Avec humour, un petit aide-mémoire illustré, très visuel, est proposé par Lise Vaudor ici. 5.5.5 Manipuler des variables factorielles ( = qualitatives ou catégorielles) Les facteurs (ou factors, an anglais) sont un type de vecteur géré nativement par R qui permettent de gérer les variables qualitatives ou catégorielles. Les facteurs sont souvent mis en regard des données labellisées utilisées dans d’autres logiciels statistiques. Les facteurs possèdent un attribut appelé niveaux (levels, en anglais) qui contient l’ensemble des valeurs qui peuvent être prises par les éléments du vecteur. Les fonctions du module {forcats} permettent de modifier les modalités d’une variable factorielle, notamment : changer les modalités des facteurs et/ou leur ordre, regrouper des modalités. On va ici utiliser la fonction fct_infreq(), pour modifier le tri des stations en fonction de leur fréquence d’apparition dans la table “prelevement”. {forcats} permet beaucoup d’autres possibilités de tri : tri manuel des facteurs avec fct_relevel() ; en fonction de la valeur d’une autre variable avec fct_reorder(); en fonction de l’ordre d’apparition des modalités avec fct_inorder(). Consulter la documentation du package {forcats} pour voir toutes les possibilités très riches de ce module. En quoi ces fonctions sont utiles ? Elles permettent notamment : lorsqu’on fait des graphiques, d’afficher les occurences les plus importantes d’abord ; de lier l’ordre d’une variable en fonction d’une autre (par exemple les code Insee des communes en fonction des régions). Exemple : ordonner les modalités d’un facteur pour améliorer l’aspect d’un graphique library(ggplot2) library(forcats) data <- data.frame(num = c(1, 8, 4, 3, 6, 7, 5, 2, 11, 3), cat = c(letters[1:10])) ggplot(data, aes(x = cat, num)) + geom_bar(stat = "identity") + xlab(label = "Facteur") + ylab(label = "Valeur") ggplot(data, aes(x = fct_reorder(cat, -num), num)) + geom_bar (stat = "identity") + xlab(label = "Facteur ordonné") + ylab(label = "Valeur") 5.6 Agréger des données : summarise() La fonction summarise() permet d’agréger des données, en appliquant une fonction sur les variables pour construire une statistique sur les observations de la table. summarise() est une fonction dite de “résumé”. À l’inverse de mutate(), quand une fonction summarise est appelée, elle retourne une seule information. La moyenne, la variance, l’effectif… sont des informations qui condensent la variable étudiée en une seule information. La syntaxe de summarise est classique. Le résultat est un dataframe. summarise(exercice, mesure_moyenne = mean(resultat_analyse, na.rm = TRUE)) On peut calculer plusieurs statistiques sur une agrégation summarise(exercice, mesure_moyenne = mean(resultat_analyse, na.rm = TRUE), mesure_total = sum(resultat_analyse, na.rm = TRUE) ) 5.6.1 Quelques fonctions d’agrégations utiles compter : n() sommer : sum() compter des valeurs non manquantes sum(!is.na()) moyenne : mean(), moyenne pondérée : weighted.mean() écart-type : sd() médiane : median(), quantile : quantile(.,quantile) minimum : min(), maximum : max() position : first(), nth(., position), last() La plupart de ces fonctions d’agrégation sont paramétrables pour indiquer comment traiter les valeurs manquantes (NA) grâce à l’argument na.rm. Si on ne souhaite pas tenir compte des valeurs manquantes pour effectuer notre synthèse, il faut indiquer na.rm = TRUE pour évacuer les valeurs manquantes du calcul, sinon, le résultat apparaîtra comme lui même manquant, car il manque des observations pour pouvoir calculer correctement notre résultat. C’est la connaissance de votre source de données et du travail en court qui déterminera comment vous souhaitez que les valeurs manquantes soit traitées. 5.7 Agréger des données par dimension : group_by() La fonction summarise() est utile, mais la plupart du temps, nous avons besoin non pas d’agréger des données d’une table entière, mais de construire des agrégations sur des sous-ensembles : par année, département… La fonction group_by() va permettre d’éclater notre table en fonction de dimensions de celle-ci. Ainsi, si on veut construire des statistiques agrégées non sur l’ensemble de la table, mais pour chacune des modalités d’une ou de plusieurs variables de la table. Il faut deux étapes : utiliser préalablement la fonction group_by() pour définir la ou les variables sur lesquelles on souhaite agréger les données, utiliser summarise() sur la table en sortie de l’étape précédente. Découper un jeu de données pour réaliser des opérations sur chacun des sous-ensembles afin de les restituer ensuite de façon organisée est appelée stratégie du split – apply – combine schématiquement, c’est cette opération qui est réalisée par dplyr dès qu’un group_by() est introduit sur une table. Exemple pour calculer les statistiques précédentes par année : exercice <- mutate(exercice, annee = year(date_prelevement)) paran <- group_by(exercice, annee) summarise(paran, mesure_moyenne = mean(resultat_analyse, na.rm = TRUE), mesure_total = sum(resultat_analyse, na.rm = TRUE)) ## # A tibble: 26 × 3 ## annee mesure_moyenne mesure_total ## <dbl> <dbl> <dbl> ## 1 1991 0.0724 1.38 ## 2 1992 0.192 4.42 ## 3 1993 0.137 2.46 ## 4 1994 0.07 2.24 ## 5 1995 0.0687 2.06 ## 6 1996 0.0867 3.99 ## 7 1997 0.0520 2.50 ## 8 1998 0.145 22.8 ## 9 1999 0.0672 44.6 ## 10 2000 0.0586 36.9 ## # ℹ 16 more rows Pour reprendre des traitements “table entière”, il faut mettre fin au group_by() par un ungroup(). La fonction summarise() accepte désormais un argument .groups qui permet d’indiquer directement comment nous souhaitons voir ré-assemblé ou non notre jeu de données. paran <- group_by(exercice, annee, code_reseau) resultat <- summarise(paran, mesure_moyenne = mean(resultat_analyse, na.rm = TRUE), mesure_total = sum(resultat_analyse, na.rm = TRUE)) ## `summarise()` has grouped output by 'annee'. You can override using the ## `.groups` argument. Si on omet de lui déclarer comment traiter les groupes en sortie, summarise() nous informe des éventuels groupes résiduels, ici resultat est toujours groupé par annee. Pour remédier à ce message ou changer le comportement de summarise(), .groups peut prendre plusieurs valeurs : \"drop_last\" : va supprimer le dernier niveau de groupement de notre jeu de données. Dans notre exemple le groupe selon code_reseau va disparaître et celui lié à annee va rester. C’est le comportement par défaut. \"drop\" : supprime tous les niveaux de groupement \"keep\" : conserve tous les niveaux de groupement. \"rowwise\" : chaque ligne devient son propre groupe. resultat <- summarise(paran, mesure_moyenne = mean(resultat_analyse, na.rm = TRUE), mesure_total = sum(resultat_analyse, na.rm = TRUE), .groups = "drop") 5.8 Le pipe Le pipe est la fonction qui va vous permettre d’écrire votre code de façon plus lisible pour vous et les utilisateurs. Comment ? En se rapprochant de l’usage usuel en grammaire. verbe(sujet, complement) devient sujet %>% verbe(complement) Quand on enchaîne plusieurs verbes, l’avantage devient encore plus évident : verbe2(verbe1(sujet, complement1), complement2) devient sujet %>% verbe1(complement1) %>% verbe2(complement2) En reprenant l’exemple précédent, sans passer par les étapes intermédiaires, le code aurait cette tête : summarise ( group_by ( mutate ( exercice, annee = year(date_prelevement) ), annee ), mesure_moyenne = mean(resultat_analyse, na.rm = TRUE), mesure_total = sum(resultat_analyse, na.rm = TRUE) ) ## # A tibble: 26 × 3 ## annee mesure_moyenne mesure_total ## <dbl> <dbl> <dbl> ## 1 1991 0.0724 1.38 ## 2 1992 0.192 4.42 ## 3 1993 0.137 2.46 ## 4 1994 0.07 2.24 ## 5 1995 0.0687 2.06 ## 6 1996 0.0867 3.99 ## 7 1997 0.0520 2.50 ## 8 1998 0.145 22.8 ## 9 1999 0.0672 44.6 ## 10 2000 0.0586 36.9 ## # ℹ 16 more rows Avec l’utilisation du pipe (raccourci clavier CTrl + Maj + M), il devient : exercice %>% mutate(annee = year(date_prelevement)) %>% group_by(annee) %>% summarise(mesure_moyenne = mean(resultat_analyse, na.rm = TRUE), mesure_total = sum(resultat_analyse, na.rm = TRUE)) ## # A tibble: 26 × 3 ## annee mesure_moyenne mesure_total ## <dbl> <dbl> <dbl> ## 1 1991 0.0724 1.38 ## 2 1992 0.192 4.42 ## 3 1993 0.137 2.46 ## 4 1994 0.07 2.24 ## 5 1995 0.0687 2.06 ## 6 1996 0.0867 3.99 ## 7 1997 0.0520 2.50 ## 8 1998 0.145 22.8 ## 9 1999 0.0672 44.6 ## 10 2000 0.0586 36.9 ## # ℹ 16 more rows 5.9 La magie des opérations groupées L’opération group_by() que nous venons de voir est très utile pour les agrégations, mais elle peut aussi servir pour créer des variables ou filtrer une table, puisque group_by() permet de traiter notre table en entrée comme autant de tables séparées par les modalités des variables de regroupement. 5.9.1 Exercice 3 A partir des données “sitadel” chargées dans l’exercice 1, effectuer les opérations suivantes en utilisant l’opérateur %>% : effectuer les mêmes calculs que ceux réalisés sur la région 52, mais sur chacune des régions –> à stocker dans ‘sit_ind’ calculer les agrégations par année civile pour chacune des régions, puis leur taux d’évolution d’une année sur l’autre (exemple : (val2015-val2014)/val2014) –> à stocker dans ‘sit_annuel’ Résultat attendu pour sit_ind : ## # A tibble: 5,356 × 12 ## date REG log_AUT ip_AUT ig_AUT colres_AUT i_AUT i_AUT_cum12 ## <chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> ## 1 200001 01 440 194 12 234 206 NA ## 2 200001 02 372 189 14 169 203 NA ## 3 200001 03 172 25 3 144 28 NA ## 4 200001 04 473 325 84 64 409 NA ## 5 200001 11 3029 754 318 1957 1072 NA ## 6 200001 21 547 274 94 179 368 NA ## 7 200001 22 475 328 16 131 344 NA ## 8 200001 23 569 445 35 89 480 NA ## 9 200001 24 1057 714 88 255 802 NA ## 10 200001 25 708 410 206 92 616 NA ## # ℹ 5,346 more rows ## # ℹ 4 more variables: i_AUT_cum12_lag12 <dbl>, i_AUT_cum_evo <dbl>, ## # log_AUT_cum12 <dbl>, part_i_AU <dbl> Résultat attendu pour sit_annuel : ## # A tibble: 468 × 10 ## REG annee log_AUT ip_AUT ig_AUT colres_AUT evol_an_log_AUT evol_an_ip_AUT ## <chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> ## 1 01 2000 6625 2776 674 3175 NA NA ## 2 02 2000 3956 1805 270 1881 NA NA ## 3 03 2000 1501 363 363 775 NA NA ## 4 04 2000 9749 4580 1246 3923 NA NA ## 5 11 2000 44443 8843 4836 30764 NA NA ## 6 21 2000 5519 3164 890 1465 NA NA ## 7 22 2000 6363 3819 721 1823 NA NA ## 8 23 2000 8803 4712 1256 2835 NA NA ## 9 24 2000 13386 7770 1867 3749 NA NA ## 10 25 2000 8678 5288 1401 1989 NA NA ## # ℹ 458 more rows ## # ℹ 2 more variables: evol_an_ig_AUT <dbl>, evol_an_colres_AUT <dbl> 5.9.2 Exercice 4 Sur les données FormationPreparationDesDonnees.RData, table exercice : 1/ calculer le taux de quantification pour chaque molécule et chacune des années : chaque molécule est identifiée par son code_parametre, le taux de quantification est le nombre de fois qu’une molécule est retrouvée (càd si code_remarque = 1) sur le nombre de fois où elle a été cherchée (càd si code_remarque = 1, 2, 7 ou 10). Pour cela : créer la variable annee créer la variable de comptage des présences pour chaque analyse (1=présent, 0=absent) créer la variable de comptage des recherches pour chaque analyse (1=recherchée, 0=non recherchée) pour chaque combinaison annee x code_parametre, calculer le taux de quantification 2/ trouver pour chaque station, sur l’année 2016, le prélèvement pour lequel la concentration cumulée, toutes substances confondues, est la plus élevée (~ le prélèvement le plus pollué). Pour cela : filtrer les concentrations quantifiées (code_remarque=1) et l’année 2016 sommer les concentrations (resultat_analyse) par combinaison code_station x code_prelevement ne conserver que le prélèvement avec le concentration maximale Résultats attendus : Résultat attendu pour le taux de quantification par molécule et année : ## # A tibble: 6,538 × 3 ## annee code_parametre taux_quantif ## <dbl> <dbl> <dbl> ## 1 1991 1129 0 ## 2 1991 1130 0 ## 3 1991 1176 0 ## 4 1991 1199 0 ## 5 1991 1212 0 ## 6 1991 1259 0 ## 7 1991 1263 100 ## 8 1991 1267 0 ## 9 1992 1101 0 ## 10 1992 1107 100 ## # ℹ 6,528 more rows Résultat attendu pour prélèvement le plus pollué de chaque station en 2016 : ## # A tibble: 176 × 3 ## libelle_station code_prelevement concentration_cumulee ## <chr> <int> <dbl> ## 1 ANGLE GUIGNARD-RETENUE 43003 0.04 ## 2 ANXURE À SAINT-GERMAIN-D'ANXURE 42228 0.02 ## 3 APREMONT-RETENUE 42895 0.035 ## 4 ARAIZE à CHATELAIS 41451 0.006 ## 5 ARON à MOULAY 41359 0.008 ## 6 AUBANCE À LOUERRE 41571 0.08 ## 7 AUBANCE à MURS-ERIGNE 41542 0.317 ## 8 AUBANCE à SAINT-SATURNIN-SUR-LOIRE 41584 0.167 ## 9 AUTHION à LES PONTS-DE-CE 42532 0.27 ## 10 AUTISE À SAINT-HILAIRE-DES-LOGES 41998 0.048 ## # ℹ 166 more rows 5.10 Les armes non conventionnelles de la préparation des donnéees Nous venons de voir les principaux verbes de manipulation d’une table de dplyr. Ces verbes acquièrent encore plus de puissance quand ils sont appelés avec les fonctions across() et/ou where(). 5.10.1 Les select helpers Répéter des opérations de nettoyage ou de typage sur les différentes variables d’un jeu de données peut s’avérer fastidieux lorsque l’on a à écrire les opérations variable par variable. La fonction select() propose cinq manières différentes de désigner les variables à sélectionner. Nous avons vu la première et la plus intuitive, qui est de nommer les variables une à une. On peut également utiliser les : qui permettent de sélectionner une liste de variables consécutives. On peut également désigner les variables à sélectionner en fonction de leur position : select(exercice, code_analyse, code_laboratoire, code_prelevement, code_parametre, code_fraction_analysee, resultat_analyse, code_remarque) %>% names() ## [1] "code_analyse" "code_laboratoire" "code_prelevement" ## [4] "code_parametre" "code_fraction_analysee" "resultat_analyse" ## [7] "code_remarque" select(exercice, code_analyse:code_remarque) %>% names() ## [1] "code_analyse" "code_laboratoire" "code_prelevement" ## [4] "code_parametre" "code_fraction_analysee" "resultat_analyse" ## [7] "code_remarque" select(exercice, -c(code_analyse:code_remarque)) %>% names() ## [1] "limite_detection" "limite_quantification" "code_intervenant" ## [4] "code_reseau" "code_station" "date_prelevement" ## [7] "code_support" "libelle_station" "date_creation" ## [10] "source" "code_masse_eau" "code_entite_hydro" ## [13] "code_troncon_hydro" "code_commune" select(exercice, 1:7) %>% names() ## [1] "code_analyse" "code_laboratoire" "code_prelevement" ## [4] "code_parametre" "code_fraction_analysee" "resultat_analyse" ## [7] "code_remarque" select(exercice, -c(1:7)) %>% names() ## [1] "limite_detection" "limite_quantification" "code_intervenant" ## [4] "code_reseau" "code_station" "date_prelevement" ## [7] "code_support" "libelle_station" "date_creation" ## [10] "source" "code_masse_eau" "code_entite_hydro" ## [13] "code_troncon_hydro" "code_commune" Sélectionner les variables en fonction de leur position peut sembler séduisant, mais attention aux problèmes de reproductibilité que cela peut poser si le jeu de données en entrée bouge un peu entre deux millésimes. On peut également sélectionner des variables selon des conditions sur leur nom. Par exemple, on peut sélectionner les variables dont le nom commence par “date”, ou se termine par “station”, ou contient “prel” ou en fonction d’une expression régulière comme “m.n” (le nom contient un “m” suivi d’un caractère suivi d’un “n”. select(exercice, starts_with("date")) %>% names() ## [1] "date_prelevement" "date_creation" select(exercice, ends_with("station")) %>% names() ## [1] "code_station" "libelle_station" select(exercice, contains("prel")) %>% names() ## [1] "code_prelevement" "date_prelevement" select(exercice, matches("m.n")) %>% names() ## [1] "code_prelevement" "date_prelevement" "code_commune" On peut également sélectionner des variables selon des conditions sur leur type, avec la fonction where(). Par exemple, sélectionner toutes les variables numériques ou toutes les variables de type caractère. select(exercice, where(is.numeric)) %>% names() ## [1] "code_analyse" "code_laboratoire" "code_prelevement" ## [4] "code_parametre" "code_fraction_analysee" "resultat_analyse" ## [7] "code_remarque" "limite_detection" "limite_quantification" ## [10] "code_support" select(exercice, where(is.character)) %>% names() ## [1] "code_station" "date_prelevement" "libelle_station" ## [4] "date_creation" "source" "code_masse_eau" ## [7] "code_entite_hydro" "code_troncon_hydro" "code_commune" On peut enfin sélectionner des variables en combinant les moyens détaillés ci-avant et en recourant aux opérateurs booléens : ! (négation), & (et), | (ou). select(exercice, 1:7 & starts_with("code")) %>% names() ## [1] "code_analyse" "code_laboratoire" "code_prelevement" ## [4] "code_parametre" "code_fraction_analysee" "code_remarque" select(exercice, starts_with("date") & !where(is.Date)) %>% names() ## [1] "date_prelevement" "date_creation" 5.10.2 Utiliser les select helpers avec les autres verbes du tidyverse 5.10.2.1 rename() et rename_with() Lorsqu’on souhaite renommer les variable une à une, la fonction rename() fonctionne de la même manière que select() : mon_df_renomme <- rename(mon_dataframe, nouveau_nom1 = ancien_nom1, nouveau_nom2 = ancien_nom2) Si l’on souhaite recourir aux select helpers, il faut utiliser rename_with(), avec la syntaxe rename_with(.data= mon_df, .fn= ma_fonction_de_renommage, .cols= les_variables_a_renommer). Exemple avec la fonction toupper() qui passe les chaînes de caractères en majuscules. rename_with(station, toupper, starts_with("code")) %>% names() ## [1] "CODE_STATION" "libelle_station" "date_creation" ## [4] "source" "CODE_MASSE_EAU" "CODE_ENTITE_HYDRO" ## [7] "CODE_TRONCON_HYDRO" "CODE_COMMUNE" Si la fonction de renommage est plus complexe qu’un simple mot, il faut recourir au pronom .x et au ~ pour la définir. Exemple avec la fonction str_sub() de {stringr} vue précédemment : rename_with(exercice, ~ str_sub(.x, start = 6, end = str_length(.x)), starts_with("code")) %>% names() ## [1] "analyse" "laboratoire" "prelevement" ## [4] "parametre" "fraction_analysee" "resultat_analyse" ## [7] "remarque" "limite_detection" "limite_quantification" ## [10] "intervenant" "reseau" "station" ## [13] "date_prelevement" "support" "libelle_station" ## [16] "date_creation" "source" "masse_eau" ## [19] "entite_hydro" "troncon_hydro" "commune" 5.10.3 filter(), mutate(), group_by(), summarise(), arrange(), transmute()… Les autres verbes de {dplyr} ont besoin de la fonction across() pour fonctionner avec les select helpers. Comme pour rename_with(), les fonctions complexes sont à déclarer avec le ~ et le pronom .x. On peut en désigner plusieurs ou leur fournir un nom qui servira de suffixe aux noms des variables calculées, en passant la ou les fonctions dans une liste : .fn=list(suffixe1 = ma_fonction1, suffixe2 = ma_fonction2). La syntaxe générale devient : monverbe(.data, across(mesvariables, malistedefonctions), across(mesvariables2, malistedefonctions2)) filter(parametre, across(starts_with("date"), ~ .x > "2015-01-01")) %>% select(1:7) ## code_parametre nom_parametre statut_parametre ## 1 7782 Desméthyl-chlortoluron Validé ## 2 7801 Cyprosulfamide Validé ## 3 7783 Haloxyfop méthyl Validé ## 4 7748 cyflufénamide Validé ## date_creation_parametre date_maj_parametre auteur_parametre parametre_calcule ## 1 2015-03-10 2015-03-27 INOVALYS Nantes FALSE ## 2 2015-04-30 2015-06-10 AERM FALSE ## 3 2015-03-10 2015-03-27 INOVALYS FALSE ## 4 2015-02-13 2015-02-13 CARSO-LSEHL FALSE mutate(exercice, across(starts_with("code") & where(is.numeric), as.factor), across(starts_with("date"), as.Date)) %>% head() %>% datatable() summarise(parametre, across(starts_with("code"), n_distinct)) ## code_parametre ## 1 435 group_by(prelevement, across(code_intervenant:code_station)) %>% summarise(across(everything(), list(nb = n_distinct)), .groups = "drop") ## # A tibble: 766 × 6 ## code_intervenant code_reseau code_station code_prelevement_nb ## <fct> <fct> <chr> <int> ## 1 44 ARS 044000001 51 ## 2 44 ARS 044000044 7 ## 3 44 ARS 044000045 5 ## 4 44 ARS 044000046 4 ## 5 44 ARS 044000047 3 ## 6 44 ARS 044000048 4 ## 7 44 ARS 044000070 6 ## 8 44 ARS 044000071 5 ## 9 44 ARS 044000076 4 ## 10 44 ARS 044000077 5 ## # ℹ 756 more rows ## # ℹ 2 more variables: date_prelevement_nb <int>, code_support_nb <int> Exemple sur l’exercice sur les données sitadel. sitadel <- read_excel("extdata/ROES_201702.xls", "AUT_REG") %>% group_by(REG) %>% mutate(across(where(is.numeric), list(cumul12 = ~ roll_sumr(.x, n = 12))), across(ends_with("cumul12"), list(evo = ~ 100 * .x / lag (.x, 12) - 100, part = ~ 100 *.x / log_AUT_cumul12))) datatable(sitadel) "],["manipuler-plusieurs-tables.html", "Chapitre 6 Manipuler plusieurs tables 6.1 Concepts généraux 6.2 Principaux exemples de jointure 6.3 Paramétrage du suffixe pour des colonnes présentes dans les deux tables 6.4 Animations de Garrick Abenduie 6.5 Exercice 5", " Chapitre 6 Manipuler plusieurs tables 6.1 Concepts généraux Le package {dplyr} possède également plusieurs fonctions permettant de travailler sur deux tables. On va pouvoir regrouper ces fonctions en plusieurs catégories de manipulations : pour fusionner des informations de deux tables entre elles : jointures transformantes, pour sélectionner des observations d’une table en fonction de celles présentes dans une autre table : jointures filtrantes, pour traiter deux tables ayant les mêmes colonnes et sélectionner sur celles-ci des observations de l’une et l’autre : opérations ensemblistes, des manipulations visant à additionner deux tables ensembles : assemblages. 6.2 Principaux exemples de jointure Dans la capture ci-dessus, les opérations de jointure supposent que la colonne x1 est présente dans a et b. Voici quelques exemples détaillant les principaux cas rencontrés : # jointure avec des noms de colonnes différentes pour la clé # `colonne_c` est une colonne de data_a et `colonne_d` est une colonne de data_b left_join(data_a, data_b, by = c("colonne_c" = "colonne_d")) # jointure sur deux colonnes # `colonne_e` et `colonne_f` sont des colonnes de data_a et de data_b left_join(data_a, data_b, by = c("colonne_e", "colonne_f")) # jointure sur deux colonnes avec noms différents # `colonne_g`et `colonne_i` sont des colonnes de data_a, `colonne_h` et `colonne_j` sont des colonnes de data_b left_join(data_a, data_b, by = c("colonne_g" = "colonne_h", "colonne_i" = "colonne_j")) 6.3 Paramétrage du suffixe pour des colonnes présentes dans les deux tables Dans le cas où des colonnes (hors jointure) sont présentes dans data_a et data_b, ces colonnes seront suffixées par : .x pour les colonnes provenant de data_a .y pour les colonnes provenant de data_b Il est possible de modifier ces suffixes en passant le paramètre suffix = c(\"_a\", \"_b\") au moment de la jointure. left_join(data_a, data_b, by = c("colonne_c" = "colonne_d"), suffix = c("_a", "_b")) 6.4 Animations de Garrick Abenduie Les animations proviennent de : https://www.garrickadenbuie.com/project/tidyexplain/ 6.4.1 Inner join 6.4.2 Left join 6.4.3 Pivot longuer / Pivot wider 6.5 Exercice 5 Dans les données FormationPreparationDesDonnees.RData, chaque analyse est effectuée à partir d’un prélèvement, lui-même réalisé au niveau d’une station. Reconstituer le dataframe exercice qui rassemble les données contenues dans les tables analyse, prelevement et station grâce à des jointures. Il faut partir de la table analyse et faire des jointures calculer le nombre d’analyses réalisées sur des molécules (identifiables par leur code_parametre) et décrites dans le référentiel parametre ; produire une liste des code_parametre associés à des analyses mais absents du référentiel ; produire une table des analyses “orphelines”, c’est-à-dire qui ne correspondent à aucun prélèvement. Résultats attendus : Résultat attendu pour les jointures entre analayse, prelevement et station ## Rows: 153,497 ## Columns: 22 ## $ code_analyse <int> 5186581, 280131, 1576225, 799894, 472800, 27671… ## $ code_laboratoire <dbl> NA, 292, NA, NA, 292, NA, NA, NA, NA, NA, NA, N… ## $ code_prelevement <int> 37593, 7715, 15517, 9566, 8332, 26792, 35625, 1… ## $ code_parametre <dbl> 1216, 1668, 1185, 1217, 1907, 1945, 1673, 1234,… ## $ code_fraction_analysee <int> 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,… ## $ resultat_analyse <dbl> 0.007, 0.050, 0.040, 0.050, 0.260, 0.020, 0.010… ## $ code_remarque <int> 10, 2, 2, 2, 1, 10, 10, 10, 10, 10, 10, 10, 2, … ## $ limite_detection <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,… ## $ limite_quantification <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,… ## $ code_intervenant <fct> NA, 104, NA, NA, 104, NA, NA, 53, NA, 44, 49, 4… ## $ code_reseau <fct> OSUR, OSUR, FREDON, OSUR, OSUR, OSUR, OSUR, ARS… ## $ code_station <chr> "04153800", "04130000", "04132500", "04214000",… ## $ date_prelevement <chr> "2014-09-16", "2003-08-05", "2008-09-01", "2007… ## $ code_support <int> NA, 3, NA, NA, 3, NA, NA, 3, NA, 3, 3, 3, NA, N… ## $ libelle_station <chr> "MOZEE à CHANTONNAY", "MAYENNE à DAON", "MAYENN… ## $ date_creation <chr> "1900-01-01", "1900-01-01", "1900-01-01", "1900… ## $ source <chr> "AELB", "AELB", "AELB", "AELB", "AELB", "AELB",… ## $ code_masse_eau <chr> "GR1950", "GR0460c", "GR0460c", "GR0121", "GR04… ## $ code_entite_hydro <chr> "N3036200", "M---0090", "M---0090", "J78-0300",… ## $ code_troncon_hydro <chr> "N3036200", "M3620090", "M3910090", "J7800300",… ## $ code_commune <chr> "85051", "53089", "49214", "44036", "53017", "5… ## $ annee <dbl> 2014, 2003, 2008, 2007, 2005, 2006, 2013, 2009,… Résultat attendu pour le nombre d’analyses réalisées sur des molécules (code_parametre) présentes dans le référentiel parametre : ## [1] 194382 Résultat attendu pour la liste des code_parametre associés à des analyses mais absents du référentiel : ## [1] 1261 1206 1673 1234 1686 1757 1666 1149 1865 1888 1225 1830 ## [13] 1506 1136 1218 1199 1664 7097 1913 1680 5526 1235 1533 1266 ## [25] 1155 1877 1215 1209 1126 1208 1189 9052 1526 1256 1903 1905 ## [37] 1866 1895 1171 1130 2027 2046 1104 1233 1193 2057 1890 1173 ## [49] 1148 1150 1103 2737 2047 1490 1464 1101 1254 1698 1540 1870 ## [61] 2912 1287 1159 1142 1257 1213 1812 1700 1194 1432 2546 6260 ## [73] 1289 1697 5537 1694 2074 1699 1951 2751 6398 1806 1228 2678 ## [85] 1814 1832 2806 2015 1809 1682 1742 3159 2807 1214 1402 1670 ## [97] 5921 0 1210 1276 1153 2028 1094 1968 6483 1124 1119 1891 ## [109] 1127 1139 1954 1503 1523 1887 1147 1522 1743 1972 1966 1763 ## [121] 2012 2976 1259 1701 1102 1231 1940 1238 2024 5416 1860 5760 ## [133] 1501 1942 6824 1280 1502 2951 1112 1975 1943 1336 1711 1716 ## [145] 1930 1764 1655 1283 1615 1976 1953 7057 2010 1805 2950 2930 ## [157] 1546 2565 5488 1880 1774 1684 1525 1959 1616 1592 1587 2769 ## [169] 2545 2750 2069 5638 2664 1702 1720 1538 1636 2984 5581 2913 ## [181] 6261 6856 1091 1875 7500 1090 1649 1614 1548 7345 2872 2987 ## [193] 1250 12143 2021 1274 1629 1465 2609 3209 1642 2748 1643 2744 ## [205] 1969 1869 7342 1591 1251 1647 2749 1116 2986 2066 1469 1388 ## [217] 2081 1245 2889 5545 1628 1648 2919 1595 1613 1957 1590 1955 ## [229] 1089 2929 2536 1160 3283 1282 1387 1458 7522 1241 3160 2732 ## [241] 1275 1651 1382 1106 1115 12098 1588 1468 1612 2916 1624 1594 ## [253] 12099 1032 1627 2733 1243 2734 1921 1273 2915 6384 1272 1117 ## [265] 1278 1653 1731 1586 1396 2887 1286 2770 5499 1305 1471 1650 ## [277] 1625 1645 1593 2868 1486 1730 1161 7150 2590 2032 1626 1589 ## [289] 1249 1386 1242 2537 1244 1644 1497 1622 2568 1577 1641 Résultat attendu pour la table des analyses “orphelines”, c’est-à-dire ne correspondent à aucun prélèvement : ## Rows: 84,535 ## Columns: 9 ## $ code_analyse <int> 3854590, 1812211, 3124130, 4245401, 3684301, 38… ## $ code_laboratoire <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,… ## $ code_prelevement <int> 32031, 17208, 28512, 33302, 31986, 32146, 17640… ## $ code_parametre <dbl> 2025, 1261, 2045, 2978, 2018, 1190, 1206, 1911,… ## $ code_fraction_analysee <int> 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,… ## $ resultat_analyse <dbl> 2e-02, 5e-02, 1e-02, 1e+01, 1e-02, 2e-02, 2e-02… ## $ code_remarque <int> 10, 10, 10, 10, 133, 10, 10, 10, 10, 10, 10, 10… ## $ limite_detection <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,… ## $ limite_quantification <dbl> 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, … "],["structurer-ses-tables.html", "Chapitre 7 Structurer ses tables 7.1 Pourquoi se pencher sur la structuration des tables ? 7.2 Les deux fonctions clefs de {tidyr}", " Chapitre 7 Structurer ses tables 7.1 Pourquoi se pencher sur la structuration des tables ? Pour bien manipuler des données, leur structuration est fondamentale. Il faut bien savoir ce qu’est : une ligne de notre table, une colonne de notre table. Sur une table non agrégée (un répertoire, une table d’enquête…), la structuration naturelle est une ligne par observation (un individu, une entreprise…), une colonne par variable (âge, taille…) sur cette observation. Mais dès qu’on agrège une telle table pour construire des tables structurées par dimensions d’analyse et indicateurs, se pose toujours la question de savoir ce qu’on va considérer comme des dimensions et comme des indicateurs. Le standard tidy data définit 3 principes pour des données propres : chaque variable est une colonne, chaque observation est une ligne, les unités d’observations différentes sont stockées dans des tables différentes. Le respect de ces règles va nous amener parfois à devoir changer la définition des lignes et colonnes de nos tables en entrée. Ci-dessous un exemple simple : la population estimée par département et genre en 2019. Ce fichier est un extrait d’un tableur mis à disposition par l’Insee. estim_pop <- read_excel('extdata/estim-pop-dep-sexe-gca-2019.xls') estim_pop ## # A tibble: 104 × 20 ## dep lib_dep Ensemble_019ans Ensemble_2039ans Ensemble_4059ans ## <chr> <chr> <dbl> <dbl> <dbl> ## 1 01 Ain 167720 150949 179476 ## 2 02 Aisne 131435 115046 137405 ## 3 03 Allier 67628 61986 87232 ## 4 04 Alpes-de-Haute-Prove… 33883 30028 43039 ## 5 05 Hautes-Alpes 30518 28633 37887 ## 6 06 Alpes-Maritimes 228072 237427 282270 ## 7 07 Ardèche 71385 62186 88572 ## 8 08 Ardennes 61006 56583 71821 ## 9 09 Ariège 31143 28962 41017 ## 10 10 Aube 74510 69537 78475 ## # ℹ 94 more rows ## # ℹ 15 more variables: Ensemble_6074ans <dbl>, Ensemble_75ansetplus <dbl>, ## # Ensemble_Total <dbl>, Homme_019ans <dbl>, Homme_2039ans <dbl>, ## # Homme_4059ans <dbl>, Homme_6074ans <dbl>, Homme_75ansetplus <dbl>, ## # Homme_Total <dbl>, Femme_019ans <dbl>, Femme_2039ans <dbl>, ## # Femme_4059ans <dbl>, Femme_6074ans <dbl>, Femme_75ansetplus <dbl>, ## # Femme_Total <dbl> En quoi ce fichier n’est pas tidy ? On retrouve 4 variables dans notre fichier : le territoire, le genre, l’âge et la population, et nos colonnes ne correspondent pas à ces variables. Quel serait la version tidy de notre fichier ? ## # A tibble: 1,872 × 5 ## dep lib_dep genre age nombre_individus ## <chr> <chr> <chr> <chr> <dbl> ## 1 01 Ain Ensemble 019ans 167720 ## 2 01 Ain Ensemble 2039ans 150949 ## 3 01 Ain Ensemble 4059ans 179476 ## 4 01 Ain Ensemble 6074ans 102788 ## 5 01 Ain Ensemble 75ansetplus 52755 ## 6 01 Ain Ensemble Total 653688 ## 7 01 Ain Homme 019ans 86359 ## 8 01 Ain Homme 2039ans 75242 ## 9 01 Ain Homme 4059ans 89278 ## 10 01 Ain Homme 6074ans 49523 ## # ℹ 1,862 more rows Comment passer facilement d’un format non tidy à un format tidy ? C’est là qu’intervient le package {tidyr}. 7.2 Les deux fonctions clefs de {tidyr} pivot_longer() permet d’empiler plusieurs colonnes (correspondant à des variables quantitatives). Elles sont repérées par création d’une variable qualitative, à partir de leurs noms. Le résultat est une table au format long. pivot_wider() fait l’inverse. Cette fonction crée autant de colonnes qu’il y a de modalités d’une variable qualitative, en remplissant chacune par le contenu d’une variable numérique. Le résultat est une table au format large. Pour avoir un aperçu illustré de ces fonctions, voir cette animation Reprenons notre table Insee d’estimation de population. Comment faire pour passer cette table dans le format tidy ? Première étape, retrouvons notre colonne population. Pour cela, il nous faut passer notre table au format long, grâce à pivot_longer(). estim_pop_tidy <- estim_pop %>% pivot_longer(-c(dep, lib_dep), values_to = "nombre_individus", names_to = "genre_age") datatable(estim_pop_tidy) Si nous voulions retrouver le format large, nous pourrions utiliser pivot_wider() estim_pop_nontidy <- estim_pop_tidy %>% pivot_wider(names_from = genre_age, values_from = nombre_individus) datatable(estim_pop_nontidy) Nous n’avons pas encore retrouvé nos deux variables genre et age, mais une seule variable mélange les deux. Pour cela, nous pouvons utiliser separate() du package {tidyr}. estim_pop_tidy <- estim_pop_tidy %>% separate(genre_age, sep = "_", into = c("genre", "age")) datatable(estim_pop_tidy) Mais pivot_longer() permet d’aller encore plus loin en spécifiant sur nos colonnes un moyen de distinguer nos deux variables directement avec l’argument names_sep. estim_pop_tidy <- estim_pop %>% pivot_longer(-c(dep, lib_dep), names_sep = "_", names_to = c("genre", "age"), values_to = "nombre_individus") datatable(estim_pop_tidy) Et pivot_wider() permet également d’utiliser deux variables pour définir les modalités à convertir en colonnes. estim_pop_tidy %>% pivot_wider(names_from = c(genre, age), values_from = nombre_individus) %>% datatable() Vous retrouverez une introduction complète à {tidyr} dans un article très bien fait de la documentation du package (en anglais). {tidyr} permet également de transformer des données sous forme de listes en dataframe tidy très simplement. "],["nettoyer-des-données-territoriales-gérer-les-évolutions-du-cog-code-officiel-géographique.html", "Chapitre 8 Nettoyer des données territoriales : gérer les évolutions du COG (code officiel géographique) 8.1 Mettre à jour une table comportant une colonne de code commune 8.2 Mettre à jour le COG et agréger aux différentes échelles 8.3 Sélectionner les territoires de ma zone de travail 8.4 Pour en savoir plus : utiliser les fonds de carte mis à disposition dans COGiter", " Chapitre 8 Nettoyer des données territoriales : gérer les évolutions du COG (code officiel géographique) Lorsque qu’on démarre en analyse de données territoriales, on est parfois surpris de constater que ce qui nous semblent être immuable, comme les contours des régions, départements, communes, ne l’est pas ! Chaque année des communes fusionnent (voire se séparent !), les régions ont bougé avec beaucoup de bruit début 2016, on a même vu récemment une commune changer de département. Bref toute chaîne de traitement de données qui a vocation a être pérennisée doit prendre en compte cette variabilité des contours territoriaux. Le COG ou Code officiel géographique des territoires est administré par l’INSEE, qui publie chaque année la nouvelle liste des communes, départements, regions, et une table de passage annuelle entre anciennes et nouvelles communes. Comme souvent avec R, des utilisateurs soucieux de partager leurs astuces ont conçu des packages pour faciliter les traitement de mise à jour du COG, on peut citer {COGugaison} de Kim Antunez, qui est très précis (conversion d’un millésime à un autre, contrôle des années de conversion, retour en arrière possible) mais seulement adapté pour les tables de données France entière, et le package DREAL Pays de la Loire, initié par Maël Theulière {COGiter}, qui est plus simple (un seul sens : la mise à jour), ce package comprend par ailleurs des services d’agrégation à différentes échelles, de gestion des noms, des contours géo, mais ne gère pas très bien les scission de communes. La mise à jour du COG d’une source avec ces packages n’est possible que si cette dernière est disponible au moins à la maille communale sans secrétisation. Dans ce chapitre sont présentés les usages les plus fréquents de {COGiter}. 8.1 Mettre à jour une table comportant une colonne de code commune Dans nos données relatives aux pesticides, la table des stations comprend le code commune de rattachement de chaque station. {COGiter} permet de tenir à jour cette information d’une fonction : library(COGiter) stations_cog_ok <- passer_au_cog_a_jour(.data = station, code_commune = code_commune, aggrege = FALSE, garder_info_supra = TRUE) Le paramètre “aggrege” sert à indiquer si on souhaite obtenir en sortie une table avec une ligne par commune à jour, en sommant les valeurs numériques de la table. Le paramètre “garder_info_supra” sert à indiquer si on souhaite obtenir en sortie une table comportant en plus les territoires supra-communaux (EPCI, DEP, REG, …) de rattachement. stations_cog_ok %>% names() ## [1] "code_station" "libelle_station" "date_creation" ## [4] "source" "code_masse_eau" "code_entite_hydro" ## [7] "code_troncon_hydro" "DEPCOM" "NOM_DEPCOM" ## [10] "EPCI" "NOM_EPCI" "DEP" ## [13] "NOM_DEP" "REG" "NOM_REG" ## [16] "DEPARTEMENTS_DE_L_EPCI" "REGIONS_DE_L_EPCI" 8.2 Mettre à jour le COG et agréger aux différentes échelles Dans nos données de l’enquête tourisme, l’INSEE nous indique que les communes utilisées pour diffuser les résultats sont de celles 2019. Elles on donc bougé depuis. Imaginions, que nous voudrions avoir les résultats de cette enquête non pas par commune, mais par EPCI et département : la fonction cogifier() nous aide à faire tout ça en un tour de main. glimpse(enq_tourisme) ## Rows: 34,953 ## Columns: 55 ## $ CODGEO <chr> "01001", "01002", "01004", "01005", "01006", "01007", "01008… ## $ LIBGEO <chr> "L'Abergement-Clémenciat", "L'Abergement-de-Varey", "Ambérie… ## $ REG <chr> "84", "84", "84", "84", "84", "84", "84", "84", "84", "84", … ## $ DEP <chr> "01", "01", "01", "01", "01", "01", "01", "01", "01", "01", … ## $ HT19 <dbl> 0, 0, 1, 2, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, … ## $ HT019 <dbl> 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, … ## $ HT119 <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, … ## $ HT219 <dbl> 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, … ## $ HT319 <dbl> 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, … ## $ HT419 <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, … ## $ HT519 <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, … ## $ HTCH19 <dbl> 0, 0, 35, 17, 0, 0, 0, 0, 15, 0, 9, 0, 10, 0, 19, 0, 0, 43, … ## $ HTCH019 <dbl> 0, 0, 0, 8, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,… ## $ HTCH119 <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, … ## $ HTCH219 <dbl> 0, 0, 35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 43, 23,… ## $ HTCH319 <dbl> 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 19, 0, 0, 0, 0, 0,… ## $ HTCH419 <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, … ## $ HTCH519 <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, … ## $ CPG19 <dbl> 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, … ## $ CPG019 <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, … ## $ CPG119 <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, … ## $ CPG219 <dbl> 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, … ## $ CPG319 <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, … ## $ CPG419 <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, … ## $ CPG519 <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, … ## $ CPGE19 <dbl> 0, 0, 0, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 121, 56,… ## $ CPGE019 <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, … ## $ CPGE119 <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, … ## $ CPGE219 <dbl> 0, 0, 0, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 121, 0, … ## $ CPGE319 <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0,… ## $ CPGE419 <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, … ## $ CPGE519 <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, … ## $ CPGEL19 <dbl> 0, 0, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 0… ## $ CPGEL019 <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, … ## $ CPGEL119 <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, … ## $ CPGEL219 <dbl> 0, 0, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 0… ## $ CPGEL319 <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, … ## $ CPGEL419 <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, … ## $ CPGEL519 <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, … ## $ CPGEO19 <dbl> 0, 0, 0, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 101, 56,… ## $ CPGEO019 <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, … ## $ CPGEO119 <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, … ## $ CPGEO219 <dbl> 0, 0, 0, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 101, 0, … ## $ CPGEO319 <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0,… ## $ CPGEO419 <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, … ## $ CPGEO519 <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, … ## $ VV19 <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, … ## $ VVUH19 <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, … ## $ VVLIT19 <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, … ## $ RT19 <dbl> 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, … ## $ RTUH19 <dbl> 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,… ## $ RTLIT19 <dbl> 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,… ## $ AJCS19 <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, … ## $ AJCSUH19 <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, … ## $ AJCSLIT19 <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, … enq_tourisme_epci_dep <- enq_tourisme %>% # on enlève les colonnes textes à mettre à jour select(-LIBGEO, -REG, -DEP) %>% cogifier(code_commune = CODGEO, communes = FALSE, epci = TRUE, departements = TRUE, regions = FALSE, metro = TRUE, franceprovince = FALSE, metrodrom = FALSE, drom = TRUE, na.rm = FALSE) glimpse(enq_tourisme_epci_dep) ## Rows: 1,352 ## Columns: 54 ## $ TypeZone <fct> Epci, Epci, Epci, Epci, Epci, Epci, Epci, Epci, Epci, Epci, … ## $ Zone <fct> "CC Faucigny-Glières", "CC du Pays de Pontchâteau St-Gildas-… ## $ CodeZone <fct> 200000172, 200000438, 200000545, 200000628, 200000800, 20000… ## $ HT19 <dbl> 6, 5, 3, 11, 8, 1, 6, 9, 5, 2, 76, 6, 6, 4, 2, 1, 15, 15, 20… ## $ HT019 <dbl> 2, 2, 0, 2, 4, 1, 3, 2, 0, 1, 14, 4, 4, 0, 1, 1, 7, 5, 5, 2,… ## $ HT119 <dbl> 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 3, 0, 0, 0, 0, 0, 1, 0, 0, 0, … ## $ HT219 <dbl> 4, 1, 2, 6, 2, 0, 2, 2, 1, 0, 14, 0, 1, 2, 1, 0, 1, 10, 3, 0… ## $ HT319 <dbl> 0, 1, 1, 2, 1, 0, 1, 4, 0, 1, 27, 2, 1, 2, 0, 0, 6, 0, 9, 0,… ## $ HT419 <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 15, 0, 0, 0, 0, 0, 0, 0, 3, 0,… ## $ HT519 <dbl> 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, … ## $ HTCH19 <dbl> 77, 92, 121, 330, 138, 8, 68, 219, 184, 24, 2414, 102, 89, 1… ## $ HTCH019 <dbl> 16, 29, 0, 60, 46, 8, 21, 17, 0, 6, 250, 50, 47, 0, 7, 10, 1… ## $ HTCH119 <dbl> 0, 0, 0, 61, 17, 0, 0, 0, 7, 0, 84, 0, 0, 0, 0, 0, 59, 0, 0,… ## $ HTCH219 <dbl> 61, 11, 98, 146, 60, 0, 28, 28, 15, 0, 417, 0, 14, 32, 6, 0,… ## $ HTCH319 <dbl> 0, 16, 23, 63, 15, 0, 19, 59, 0, 18, 994, 52, 28, 82, 0, 0, … ## $ HTCH419 <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 162, 0, 538, 0, 0, 0, 0, 0, 0, 0, 11… ## $ HTCH519 <dbl> 0, 36, 0, 0, 0, 0, 0, 115, 0, 0, 131, 0, 0, 0, 0, 0, 0, 0, 0… ## $ CPG19 <dbl> 2, 7, 1, 5, 1, 0, 6, 11, 3, 1, 9, 2, 10, 4, 2, 0, 2, 5, 0, 1… ## $ CPG019 <dbl> 1, 3, 0, 1, 0, 0, 3, 2, 1, 1, 2, 1, 2, 3, 0, 0, 0, 3, 0, 0, … ## $ CPG119 <dbl> 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, … ## $ CPG219 <dbl> 1, 1, 0, 0, 0, 0, 2, 2, 2, 0, 1, 1, 3, 0, 1, 0, 0, 0, 0, 0, … ## $ CPG319 <dbl> 0, 2, 0, 2, 1, 0, 0, 5, 0, 0, 5, 0, 5, 1, 1, 0, 2, 0, 0, 1, … ## $ CPG419 <dbl> 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, … ## $ CPG519 <dbl> 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, … ## $ CPGE19 <dbl> 103, 419, 220, 603, 166, 0, 264, 922, 132, 35, 746, 142, 657… ## $ CPGE019 <dbl> 34, 101, 0, 30, 0, 0, 77, 145, 40, 35, 71, 100, 37, 106, 0, … ## $ CPGE119 <dbl> 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 0, 0… ## $ CPGE219 <dbl> 69, 6, 0, 0, 0, 0, 87, 135, 92, 0, 54, 42, 79, 0, 17, 0, 0, … ## $ CPGE319 <dbl> 0, 142, 0, 222, 166, 0, 0, 478, 0, 0, 505, 0, 541, 65, 224, … ## $ CPGE419 <dbl> 0, 170, 220, 276, 0, 0, 100, 110, 0, 0, 116, 0, 0, 0, 0, 0, … ## $ CPGE519 <dbl> 0, 0, 0, 75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,… ## $ CPGEL19 <dbl> 2, 76, 114, 116, 1, 0, 3, 254, 23, 0, 7, 27, 108, 73, 63, 0,… ## $ CPGEL019 <dbl> 2, 32, 0, 30, 0, 0, 2, 30, 23, 0, 7, 27, 28, 33, 0, 0, 0, 40… ## $ CPGEL119 <dbl> 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,… ## $ CPGEL219 <dbl> 0, 0, 0, 0, 0, 0, 1, 12, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0… ## $ CPGEL319 <dbl> 0, 18, 0, 8, 1, 0, 0, 158, 0, 0, 0, 0, 58, 40, 63, 0, 32, 0,… ## $ CPGEL419 <dbl> 0, 26, 114, 23, 0, 0, 0, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0… ## $ CPGEL519 <dbl> 0, 0, 0, 55, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,… ## $ CPGEO19 <dbl> 101, 343, 106, 487, 165, 0, 261, 668, 109, 35, 739, 115, 549… ## $ CPGEO019 <dbl> 32, 69, 0, 0, 0, 0, 75, 115, 17, 35, 64, 73, 9, 73, 0, 0, 0,… ## $ CPGEO119 <dbl> 0, 0, 0, 0, 0, 0, 0, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 0, 0… ## $ CPGEO219 <dbl> 69, 6, 0, 0, 0, 0, 86, 123, 92, 0, 54, 42, 57, 0, 17, 0, 0, … ## $ CPGEO319 <dbl> 0, 124, 0, 214, 165, 0, 0, 320, 0, 0, 505, 0, 483, 25, 161, … ## $ CPGEO419 <dbl> 0, 144, 106, 253, 0, 0, 100, 71, 0, 0, 116, 0, 0, 0, 0, 0, 0… ## $ CPGEO519 <dbl> 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,… ## $ VV19 <dbl> 0, 1, 0, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, … ## $ VVUH19 <dbl> 0, 20, 0, 0, 205, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,… ## $ VVLIT19 <dbl> 0, 76, 0, 0, 686, 0, 146, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0… ## $ RT19 <dbl> 0, 0, 0, 0, 1, 0, 0, 6, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 4, 0, … ## $ RTUH19 <dbl> 0, 0, 0, 0, 746, 0, 0, 440, 0, 0, 70, 0, 0, 0, 0, 0, 0, 0, 3… ## $ RTLIT19 <dbl> 0, 0, 0, 0, 4056, 0, 0, 2233, 0, 0, 360, 0, 0, 0, 0, 0, 0, 0… ## $ AJCS19 <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, … ## $ AJCSUH19 <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23,… ## $ AJCSLIT19 <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65,… 8.3 Sélectionner les territoires de ma zone de travail Et si je ne souhaite que les territoires de ma région ou de mon département ? # Département du Nord enq_tourisme_epci_dep %>% filtrer_cog(dep = "59") ## # A tibble: 18 × 54 ## TypeZone Zone CodeZone HT19 HT019 HT119 HT219 HT319 HT419 HT519 HTCH19 ## <fct> <fct> <fct> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> ## 1 Epci CA du… 2000306… 2 0 1 0 1 0 0 61 ## 2 Epci CC de… 2000409… 9 4 0 0 4 1 0 130 ## 3 Epci CC de… 2000409… 3 0 0 0 3 0 0 107 ## 4 Epci CC Pé… 2000419… 2 0 0 0 2 0 0 49 ## 5 Epci CA de… 2000421… 5 1 0 1 2 1 0 204 ## 6 Epci CC Co… 2000432… 2 1 0 0 1 0 0 35 ## 7 Epci CC du… 2000433… 2 2 0 0 0 0 0 29 ## 8 Epci CA Ma… 2000433… 10 2 0 2 6 0 0 420 ## 9 Epci CC du… 2000434… 4 2 0 0 2 0 0 65 ## 10 Epci CA Do… 2000446… 10 2 0 1 6 1 0 527 ## 11 Epci CA de… 2000685… 11 6 0 0 5 0 0 445 ## 12 Epci Métro… 2000932… 113 29 4 15 45 17 3 7407 ## 13 Epci CU de… 2459004… 32 18 2 7 4 1 0 1371 ## 14 Epci CC Fl… 2459007… 1 1 0 0 0 0 0 52 ## 15 Epci CC du… 2459010… 0 0 0 0 0 0 0 0 ## 16 Epci CC Co… 2459011… 0 0 0 0 0 0 0 0 ## 17 Epci CA Va… 2459011… 20 9 0 5 4 2 0 1123 ## 18 Départements Nord 59 226 77 7 31 85 23 3 12025 ## # ℹ 43 more variables: HTCH019 <dbl>, HTCH119 <dbl>, HTCH219 <dbl>, ## # HTCH319 <dbl>, HTCH419 <dbl>, HTCH519 <dbl>, CPG19 <dbl>, CPG019 <dbl>, ## # CPG119 <dbl>, CPG219 <dbl>, CPG319 <dbl>, CPG419 <dbl>, CPG519 <dbl>, ## # CPGE19 <dbl>, CPGE019 <dbl>, CPGE119 <dbl>, CPGE219 <dbl>, CPGE319 <dbl>, ## # CPGE419 <dbl>, CPGE519 <dbl>, CPGEL19 <dbl>, CPGEL019 <dbl>, ## # CPGEL119 <dbl>, CPGEL219 <dbl>, CPGEL319 <dbl>, CPGEL419 <dbl>, ## # CPGEL519 <dbl>, CPGEO19 <dbl>, CPGEO019 <dbl>, CPGEO119 <dbl>, … # Région Bretagne enq_tourisme_epci_dep %>% filtrer_cog(reg = "53", garder_supra = TRUE) %>% arrange(desc(TypeZone)) ## # A tibble: 1,352 × 54 ## TypeZone Zone CodeZone HT19 HT019 HT119 HT219 HT319 HT419 HT519 HTCH19 ## <fct> <fct> <fct> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> ## 1 France France mé… FRMETRO 17720 4690 405 4363 5957 1936 369 642779 ## 2 France Départeme… DROM 229 102 2 29 64 27 5 11440 ## 3 Epci CC Faucig… 2000001… 6 2 0 4 0 0 0 77 ## 4 Epci CC du Pay… 2000004… 5 2 0 1 1 0 1 92 ## 5 Epci CC des Po… 2000005… 3 0 0 2 1 0 0 121 ## 6 Epci CC Rhône … 2000006… 11 2 1 6 2 0 0 330 ## 7 Epci CC Coeur … 2000008… 8 4 1 2 1 0 0 138 ## 8 Epci CC de la … 2000009… 1 1 0 0 0 0 0 8 ## 9 Epci CC Sauldr… 2000009… 6 3 0 2 1 0 0 68 ## 10 Epci CC du Pay… 2000048… 9 2 0 2 4 0 1 219 ## # ℹ 1,342 more rows ## # ℹ 43 more variables: HTCH019 <dbl>, HTCH119 <dbl>, HTCH219 <dbl>, ## # HTCH319 <dbl>, HTCH419 <dbl>, HTCH519 <dbl>, CPG19 <dbl>, CPG019 <dbl>, ## # CPG119 <dbl>, CPG219 <dbl>, CPG319 <dbl>, CPG419 <dbl>, CPG519 <dbl>, ## # CPGE19 <dbl>, CPGE019 <dbl>, CPGE119 <dbl>, CPGE219 <dbl>, CPGE319 <dbl>, ## # CPGE419 <dbl>, CPGE519 <dbl>, CPGEL19 <dbl>, CPGEL019 <dbl>, ## # CPGEL119 <dbl>, CPGEL219 <dbl>, CPGEL319 <dbl>, CPGEL419 <dbl>, … 8.4 Pour en savoir plus : utiliser les fonds de carte mis à disposition dans COGiter COGiter contient des fonds de cartes des contours administratifs, conçus à partir des couches admin-express de l’IGN et dont la géométrie a été encore simplifiée pour répondre aux besoins de visualisation statistique. Voici un exemple d’usage très sommaire : departements_geo %>% inner_join(enq_tourisme_epci_dep, by = c("DEP" = "CodeZone")) %>% select(HT19) %>% plot() Obtenir la liste des fonds de cartes et des fonctionnalités géo : https://maeltheuliere.github.io/COGiter/articles/filtre_geo.html "],["exercice-6-les-données-majic.html", "Chapitre 9 Exercice 6 : les données majic", " Chapitre 9 Exercice 6 : les données majic Calculer à partir des tables fournies dans le fichier majic.RData issues des fichiers fonciers (cf. http://piece-jointe-carto.developpement-durable.gouv.fr/NAT004/DTerNP/html3/_ff_descriptif_tables_image.html#pnb10) un indicateur d’étalement urbain entre 2009 et 2014 à la commune et à l’EPCI sur la région Pays de la Loire (départements 44, 49, 53, 72 et 85), et catégoriser chaque territoire. Définitions : artificialisation = dcnt07 + dcnt09 + dcnt10 + dcnt11 + dcnt12 + dcnt13 indicateur_etalement_simple = évolution de l’artificialisation / évolution de la population indicateur_etalement_avance, indicateur catégoriel qui vaut : 1 si la population progresse ou reste stable alors que l’artificialisation recule ; 2a si la population et l’artificialisation progressent ou sont stables et l’étalement urbain est inférieur ou égal à 1 (ou pop stable) ; 2b si la population et l’artificialisation reculent et l’indicateur d’étalement urbain est supéreur à 1 ; 2c si la population recule et l’indicateur d’étalement est compris entre 0 et 1 (inclus) ; 3 si la population progresse, l’artificialisation progresse plus vite que la population, tout en restant inférieure ou égale à 4,9 m² ; 4 si la population progresse, l’artificialisation est supérieure à 4,9 m², elle progresse plus vite que la population mais au plus 2 fois plus vite ; 5 si la population progresse, l’artificialisation progresse plus de 2 fois plus vite que la population et est supérieure à 4,9 m² ; 6 si la population recule et l’indicateur d’étalement urbain est négatif. Résultats attendus : Résultat attendu : création de l’indicateur artificialisation pour les deux millésimes de majic (solution COGiter) ## Rows: 1,305 ## Columns: 4 ## $ TypeZone <fct> Communes, Communes, Communes, Communes, Communes, Communes,… ## $ Zone <fct> "Abbaretz", "Aigrefeuille-sur-Maine", "Ancenis-Saint-Géréon… ## $ CodeZone <fct> 44001, 44002, 44003, 44005, 44006, 44007, 44009, 44010, 440… ## $ artif_2009 <dbl> 3064748, 2408844, 6859785, 6101987, 2379588, 3042688, 50259… ## Rows: 1,305 ## Columns: 4 ## $ TypeZone <fct> Communes, Communes, Communes, Communes, Communes, Communes,… ## $ Zone <fct> "Abbaretz", "Aigrefeuille-sur-Maine", "Ancenis-Saint-Géréon… ## $ CodeZone <fct> 44001, 44002, 44003, 44005, 44006, 44007, 44009, 44010, 440… ## $ artif_2014 <dbl> 3160057, 2485622, 7103107, 6496868, 2419875, 3105298, 52452… Résultat attendu : création de les indicateurs pop_2009 et pop_2014 pour les deux millésimes de majic (solution COGiter) ## Rows: 1,305 ## Columns: 4 ## $ TypeZone <fct> Communes, Communes, Communes, Communes, Communes, Communes, C… ## $ Zone <fct> "Abbaretz", "Aigrefeuille-sur-Maine", "Ancenis-Saint-Géréon",… ## $ CodeZone <fct> 44001, 44002, 44003, 44005, 44006, 44007, 44009, 44010, 44012… ## $ pop_2009 <dbl> 1909, 3214, 10639, 5894, 1810, 2465, 8265, 3185, 2595, 2591, … ## Rows: 1,305 ## Columns: 4 ## $ TypeZone <fct> Communes, Communes, Communes, Communes, Communes, Communes, C… ## $ Zone <fct> "Abbaretz", "Aigrefeuille-sur-Maine", "Ancenis-Saint-Géréon",… ## $ CodeZone <fct> 44001, 44002, 44003, 44005, 44006, 44007, 44009, 44010, 44012… ## $ pop_2014 <dbl> 2042, 3714, 10783, 6680, 1830, 2601, 8747, 3086, 2769, 2927, … Résultat attendu : jointude implicite sur idcom et création de l’indicateur d'étalement urbain(solution COGiter) : ## Rows: 1,305 ## Columns: 11 ## $ TypeZone <fct> Communes, Communes, Communes, Communes, Co… ## $ Zone <fct> "Abbaretz", "Aigrefeuille-sur-Maine", "Anc… ## $ CodeZone <fct> 44001, 44002, 44003, 44005, 44006, 44007, … ## $ artif_2009 <dbl> 3064748, 2408844, 6859785, 6101987, 237958… ## $ artif_2014 <dbl> 3160057, 2485622, 7103107, 6496868, 241987… ## $ pop_2009 <dbl> 1909, 3214, 10639, 5894, 1810, 2465, 8265,… ## $ pop_2014 <dbl> 2042, 3714, 10783, 6680, 1830, 2601, 8747,… ## $ evoarti <dbl> 3.109847857, 3.187337993, 3.547079099, 6.4… ## $ evopop <dbl> 6.966998, 15.556938, 1.353511, 13.335596, … ## $ ies <dbl> 0.446368388, 0.204882086, 2.620651010, 0.4… ## $ indicateur_etalement_avance <chr> "2a", "2a", "3", "2a", "3", "2a", "2a", "6… Résultat attendu pour etalement_urbain_commune: ## Rows: 1,233 ## Columns: 11 ## $ TypeZone <fct> Communes, Communes, Communes, Communes, Co… ## $ Zone <fct> "Abbaretz", "Aigrefeuille-sur-Maine", "Anc… ## $ CodeZone <fct> 44001, 44002, 44003, 44005, 44006, 44007, … ## $ artif_2009 <dbl> 3064748, 2408844, 6859785, 6101987, 237958… ## $ artif_2014 <dbl> 3160057, 2485622, 7103107, 6496868, 241987… ## $ pop_2009 <dbl> 1909, 3214, 10639, 5894, 1810, 2465, 8265,… ## $ pop_2014 <dbl> 2042, 3714, 10783, 6680, 1830, 2601, 8747,… ## $ evoarti <dbl> 3.109847857, 3.187337993, 3.547079099, 6.4… ## $ evopop <dbl> 6.966998, 15.556938, 1.353511, 13.335596, … ## $ ies <dbl> 0.446368388, 0.204882086, 2.620651010, 0.4… ## $ indicateur_etalement_avance <chr> "2a", "2a", "3", "2a", "3", "2a", "2a", "6… Résultat attendu pour etalement_urbain_epci: ## Rows: 71 ## Columns: 11 ## $ TypeZone <fct> Epci, Epci, Epci, Epci, Epci, Epci, Epci, … ## $ Zone <fct> "CC du Pays de Pontchâteau St-Gildas-des-B… ## $ CodeZone <fct> 200000438, 200023778, 200033298, 200040475… ## $ artif_2009 <dbl> 27594293, 44299964, 25161639, 24880690, 16… ## $ artif_2014 <dbl> 28629232, 46277932, 26955382, 25836264, 18… ## $ pop_2009 <dbl> 31965, 45278, 27906, 18370, 17608, 29131, … ## $ pop_2014 <dbl> 35112, 48610, 28168, 19004, 17017, 29304, … ## $ evoarti <dbl> 3.750555, 4.464943, 7.128880, 3.840625, 7.… ## $ evopop <dbl> 9.8451431, 7.3589823, 0.9388662, 3.4512793… ## $ ies <dbl> 0.3809548, 0.6067337, 7.5930733, 1.1128120… ## $ indicateur_etalement_avance <chr> "2a", "2a", "5", "3", "6", "3", "5", "2a",… Résultat attendu pour le graphique (vu au M5) : "],["aller-plus-loin.html", "Chapitre 10 Aller plus loin", " Chapitre 10 Aller plus loin Quelques références : R for data science : http://r4ds.had.co.nz/transform.html {dplyr}, Introduction : https://dplyr.tidyverse.org/articles/dplyr.html {dplyr}, manipulation de deux tables : https://dplyr.tidyverse.org/articles/two-table.html {tidyr} : https://tidyr.tidyverse.org/ {tidyr}, fonctions pivot : https://tidyr.tidyverse.org/articles/pivot.html Aide mémoire de Rstudio sur {dplyr} et {tidyr} (assez ancien) : https://www.rstudio.com/wp-content/uploads/2016/01/data-wrangling-french.pdf Si vous préférez vous mettre à {data.table} https://s3.amazonaws.com/assets.datacamp.com/img/blog/data+table+cheat+sheet.pdf "],["404.html", "Page not found", " Page not found The page you requested cannot be found (perhaps it was moved or renamed). You may want to try searching to find the page's new location, or use the table of contents to find the page you are looking for. "]]
+[["index.html", "Préparer ses données avec R et le Tidyverse Chapitre 1 Introduction 1.1 Le parcours de formation 1.2 Le groupe de référents R du pôle ministériel 1.3 Objectifs du module 2", " Préparer ses données avec R et le Tidyverse Maël Theulière & Bruno Terseur 26 August 2024 Chapitre 1 Introduction Crédit photographique Sébastien Colas 1.1 Le parcours de formation Ce dispositif de formation vise à faire monter en compétence les agents du MTECT (Ministère de la Transition écologique et de la Cohésion des territoires) et du MTE (Ministère de la Transition énergétique) dans le domaine de la science de la donnée avec le logiciel R. Il est conçu pour être déployé à l’échelle nationale par le réseau des CVRH (Centre de Valorisation des Ressources Humaines). Le parcours proposé est structuré en modules de 2 jours chacun. Avoir suivi les deux premiers (ou disposer d’un niveau équivalent) est un pré-requis pour suivre les suivants qui sont proposés “à la carte” : Module 1 : Socle - Premier programme en R Module 2 : Socle - Préparation des données Module 3 : Statistiques descriptives Module 4 : Analyse des données multi-dimensionnelles Module 5 : Datavisualisation : Produire des graphiques, des cartes et des tableaux Module 6 : Publications reproductibles avec RMarkdown (à venir) Module 7 : Analyse spatiale Module 8 : Big data et optimisation du code (à venir) Module 9 : Applications interactives avec RShiny (à venir) La mise à disposition des supports de formation se fait par la page d’accueil du parcours de formation. Ces supports sont en licence ouverte. Si vous souhaitez accéder aux sources ou aux données mobilisées pendant les formations, vous pouvez directement les télécharger depuis le Github du pôle ministériel. Un package d’exercices, {savoirfR} rassemble toutes les données et les consignes d’exercices de ce parcours de formation (Modules 1, 2, 5 et 7 seulement pour l’instant). Pour vous tenir au courant de l’offre de formation proposée par le réseau des CVRH, consultez la plateforme OUPS (un accès intranet MTECT-MTE est nécessaire). Vous pouvez vous y abonner pour recevoir les annonces de formation qui vous intéressent. Pour échanger de l’information, discuter autour de R ou encore faire part de difficultés et trouver ensemble les solutions, il existe deux canaux d’entraide : s’inscrire en envoyant un message vide à l’adresse sympa@developpement-durable.gouv.fr ; rejoindre le salon Tchap #utilisateurs_r. 1.2 Le groupe de référents R du pôle ministériel Un groupe pour structurer une offre de formations sur R Un réseau d’entraide 1.3 Objectifs du module 2 Ce module va vous permettre de découvrir un ensemble de méthodes sous R afin de préparer ses données. Préparer ses données sous R, cela veut dire : Savoir les importer dans un environnement R, Mettre ses données dans de bons formats (date, catégorielle) et gérer les données manquantes, Rajouter des variables en fonction de variables existantes, Regrouper des modalités de variables, Joindre des tables entre elles pour obtenir des informations de plusieurs sources, Agréger des données, Bien définir notre table de travail en fonction des indicateurs à analyser et à leurs dimensions d’analyse. … Bref, tout le travail technique préalable entre la collecte de la donnée et sa valorisation proprement dite. On estime qu’un scientifique de la donnée passe en général la moitié de son temps à cela. Sous R, comme souvent, il y a plusieurs façons d’aborder cette question. Ce module de formation privilegie l’exploration des packages du framework tidyverse, qui ont l’avantage d’aborder les différentes phases de préparation des données d’une façon intégrée et cohérente, que ce soit entre elles, ou avec d’autres. "],["le-tidyverse.html", "Chapitre 2 Le tidyverse 2.1 Présentation des packages 2.2 Les spécificités du tidyverse 2.3 D’autres approches possibles", " Chapitre 2 Le tidyverse Le tidyverse est un ensemble de packages proposant une syntaxe cohérente pour remplir l’essentiel des traitements propres à la science de la données, de la lecture des données à la valorisation, en passant par la modélisation. Le manifeste du tidyverse comprend 4 principes clefs pour les packages : Utiliser les structures de données existantes : ne pas créer des objets ad hoc ; Utiliser l’opérateur pipe ; S’intégrer dans l’approche de programmation fonctionnelle de R ; Designé pour les être humains : favoriser la facilité d’usage à la performance machine. 2.1 Présentation des packages 2.1.1 Des packages pour lire des données 2.1.1.1 tidyverse {readr} pour les fichiers plats {readxl} pour les fichiers tableur Excel {haven} pour les données stockées sous des formats propriétaires (SAS, SPSS, …) 2.1.1.2 Hors tidyverse {odbc} / {Rposgresql} pour accéder à des données stockées sous forme de base de données {sf} pour lire des données spatiales {rsdmx} pour lire des données sdmx 2.1.2 Des packages pour manipuler des données 2.1.2.1 tidyverse {dplyr} fonctions correspondant à des “verbes” pour manipuler ses données {tidyr} fonctions pour modifier l’agencement de nos tables entre les lignes et les colonnes 2.1.3 Des packages pour nettoyer des données 2.1.3.1 tidyverse {forcats} permet de manipuler les variables de type catégoriel (ou factor en R) {stringr} permet de manipuler des chaînes de caractères {lubridate} permet de manipuler des dates 2.1.3.2 Hors tidyverse {stringi} permet de manipuler des chaînes de caractères {RcppRoll} qui regroupe des opérations fenêtrées ou glissantes 2.2 Les spécificités du tidyverse Quelques spécificités des fonctions de ce framework : Ces packages sont orientés manipulation de dataframes et non de vecteurs En conséquence, on utilise jamais l’indexation des colonnes de tables (le “$”) pour appeler une variable Chaque fonction ne fait qu’une chose et une seule (c’est une opération élémentaire) L’ensemble des fonctions obéissent à la même logique, ce qui permet de simplifier l’apprentissage L’ensemble de ces opérations élémentaires peuvent s’enchaîner à la manière d’un ETL avec le pipe 2.3 D’autres approches possibles Les fonctions que nous allons voir obéissent à une logique intégrée et simple, qui permet des manipulations complexes, à partir du moment ou l’on est capable d’identifier et de sérier chaque opération élémentaire à réaliser. D’autres packages permettent également de réaliser ce type de manipulations. La différence est qu’ils sont souvent dédiés à une tâche spécifique, ce qui rend la cohérence moins évidente lorsque l’on doit réaliser plusieurs opérations. Un autre package propose toutefois une vision intégrée de la sorte : {data.table}. Plusieurs différences sont à noter : {data.table} est plus rapide sur d’importants volumes de données, le code est très concis. {dplyr} est plus simple à apprendre, le code est plus lisible, il peut s’appliquer à des formats de données multiples, il s’intègre dans un framework global qui va de la lecture des données ({readr}, {readxl}, {haven}…) à leur valorisation ({ggplot2}). "],["bien-commencer.html", "Chapitre 3 Bien commencer 3.1 Créer un projet sous Rstudio pour vous permettre de recenser vos travaux. 3.2 Intégrer vos données 3.3 Créer votre arborescence de projet 3.4 Utilisation du package savoirfR 3.5 Activer les packages nécessaires 3.6 Bien structurer ses projets data", " Chapitre 3 Bien commencer 3.1 Créer un projet sous Rstudio pour vous permettre de recenser vos travaux. Pourquoi travailler avec les projets Rstudio plutôt que les scripts R ? Cela permet la portabilité : le répertoire de travail par défaut d’un projet est le répertoire où est ce projet. Si vous transmettez celui-ci à un collègue, le fait de lancer un programme ne dépend pas de l’arborescence de votre machine. Fini les setwd(\"chemin/qui/marche/uniquement/sur/mon/poste\") ! Toujours sur la portabilité, un projet peut être utilisé avec un outil comme renv qui va vous intégrer en interne au projet l’ensemble des packages nécessaires au projet. Cela permet donc à votre collègue à qui vous passez votre projet de ne pas avoir à les installer et, surtout, si vous mettez à jour votre environnement R, votre projet restera toujours avec les versions des packages avec lesquelles vous avez fait tourner votre projet à l’époque. Cela évite d’avoir à subir les effets d’une mise à jour importante d’un package qui casserait votre code. Pour activer renv sur un projet, il faut l’installer avec install.packages(\"renv\"). Pour intialiser la sauvegarde des packages employés dans le projet, il faut utiliser renv::init() Les packages chargés dans le projet sont enregistrés dans un sous-dossier dédié. En cours de travail sur le projet, la commande renv::snapshot() permet de faire une sauvegarde, la commande renv::restore() permet de charger la dernière sauvegarde. En savoir plus sur renv Cela permet de se forcer à travailler en mode projet : on intègre à un seul endroit tout ce qui est lié à un projet : données brutes, données retravaillées, scripts, illustrations, documentations, publications… et donc y compris les packages avec renv. On peut travailler sur plusieurs projets en même temps, Rstudio ouvre autant de sessions que de projets dans ce cas. Les projets Rstudio intègrent une interface avec les outils de gestion de version Git et SVN. Cela veut dire que vous pouvez versionner votre projet et l’héberger simplement comme répertoire sur des plateformes de gestion de code telle que Github ou Gitlab. Pour créer un projet : Cliquez sur Project en haut à droite puis New Project. Cliquez sur New Directory. 3.2 Intégrer vos données Une bonne pratique est de créer un sous répertoire /data pour stocker les données sur lesquelles vous aurez à travailler. Vous pouvez le faire depuis l’explorateur de fichiers de votre système d’exploitation ou directement à partir de l’explorateur de fichiers de RStudio. Cela marche bien quand on a un seul type de données, mais en général on va avoir à travailler sur des données brutes que l’on va retravailler ensuite et vouloir stocker à part. Si par la suite vous souhaitez avoir des exemples de bonnes pratiques sur comment structurer vos données, vous pouvez vous référer au chapitre data du livre d’Hadley Wickham sur la construction de packages R (tout package R étant aussi un projet !). 3.3 Créer votre arborescence de projet Créer un répertoire /src ou vous mettrez vos scripts R. Créer un répertoire /figures ou vous mettrez vos illustrations issues de R. 3.4 Utilisation du package savoirfR Pour faciliter le déroulé de ce module, l’ensemble des exercices (énoncés, corrigés et données) a été intégré à un package réalisé par le groupe des référents R : {savoirfR} install.packages('remotes') remotes::install_github("MTES-MCT/savoirfR") Pour l’utiliser, il suffit de créer un nouveau projet dans un nouveau répertoire, en sélectionnant le “Project Type” Exercice Parcours R MTES-MCT. Remplissez et sélectionnez le module suivi. 3.5 Activer les packages nécessaires Commencer par rajouter un script dans le répertoire /src à votre projet qui commencera par : activer l’ensemble des packages nécessaires, charger les données dont vous aurez besoin. library(tidyverse) library(lubridate) library(RcppRoll) library(DT) library(readxl) library(dbplyr) library(RPostgreSQL) library(rsdmx) library(sf) library(stringi) sitadel <- read_excel("extdata/ROES_201702.xls", sheet = "AUT_REG", col_types = c ("text","text","numeric","numeric","numeric","numeric")) load(file = "extdata/FormationPreparationDesDonnees.RData") 3.6 Bien structurer ses projets data Plusieurs documents peuvent vous inspirer sur la structuration de vos projets data par la suite. En voici quelques-uns : https://github.com/pavopax/new-project-template https://nicercode.github.io/blog/2013-04-05-projects/ https://www.inwt-statistics.com/read-blog/a-meaningful-file-structure-for-r-projects.html http://projecttemplate.net/architecture.html À partir du moment où quelques grands principes sont respectés (un répertoire pour les données brutes en lecture seule par exemple), le reste est surtout une question d’attirance plus forte pour l’une ou l’autre solution. L’important est de vous tenir ensuite à conserver toujours la même arborescence dans vos projets afin de vous y retrouver plus simplement. "],["lire-des-données.html", "Chapitre 4 Lire des données 4.1 Lire des fichiers locaux 4.2 Lire des données disponibles sur le web : téléchargement de fichiers 4.3 Lire des données disponibles sur le web via API 4.4 Lire des fichiers avec une dimension spatiale 4.5 Lire des données sous PostgreSQL 4.6 Lire des fichiers au format parquet", " Chapitre 4 Lire des données La première étape d’une chaîne de traitement est d’accéder aux données à traiter. R propose énormément de solutions pour ce faire. Quelle que soit la solution choisie, l’important est de chercher à rendre votre travail reproductible : c’est à dire reproductible dans le temps et reproductible par un collègue, sur une autre machine. L’idéal est indiquer dans le script de préparation des données comment le fichier est arrivé sur votre poste de travail, soit en codant les instructions de téléchargement, soit en ajoutant des commentaires qui vous permettront plus tard de reconstituer le jeu de données que vous utilisez. 4.1 Lire des fichiers locaux 4.1.1 {readxl} : lire des données Excel La fonction read_excel() du package {readxl} permet d’importer les données d’un fichier Excel. On peut spécifier : la feuille, les colonnes, les lignes ou la zone à importer, les lignes à supprimer avant importation, si on souhaite importer la première ligne comme des noms de variables ou non, le format des variables importées, la valeur qui sera interprétée comme étant la valeur manquante. library(readxl) sitadel <- read_excel("extdata/ROES_201702.xls", sheet = "AUT_REG", col_types = c ("text","text","numeric","numeric","numeric","numeric")) datatable(sitadel) 4.1.2 read_delim() : lire des fichiers plats La fonction read_delim() de {readr} permet d’importer les données d’un fichier csv. Elle fonctionne de la même façon que read_excel(). On peut spécifier : le caractère délimiteur de colonne, les lignes à supprimer avant importation, si on souhaite importer la première ligne comme des noms de variables ou non, le locale du fichier, la valeur qui sera interprétée comme étant la valeur manquante. read_csv(), read_csv2() et read_tsv() sont des implémentations pré-renseignées de read_delim pour lire des fichiers plats avec séparateurs , ; et tabulaire. 4.2 Lire des données disponibles sur le web : téléchargement de fichiers Parfois, les données que nous exploitons sont disponibles au téléchargement sur le web. 4.2.1 Exemple site de l’INSEE, avec dezippage Il est possible, directement depuis R, de télécharger ces données et, si nécessaire, de les décompresser (dans le répertoire de travail). Exemple sur les données 2019 de l’enquête INSEE sur les hébergements touristiques. # présentation des données sur https://www.insee.fr/fr/statistiques/2021703 url <- "https://www.insee.fr/fr/statistiques/fichier/2021703/base-cc-tourisme-2019-geo2019.zip" download.file(url, destfile = "extdata/base-cc-tourisme-2019-geo2019.zip") unzip(zipfile = "extdata/base-cc-tourisme-2019-geo2019.zip", exdir = "extdata") enq_tourisme <- read_excel("extdata/base-cc-tourisme-2019-geo2019.xls", sheet = "COM", skip = 5) datatable(head(enq_tourisme), options = list(dom = 't')) 4.2.2 Exemple données sur les logements vacants depuis data.gouv.fr (fichier locvac produit par le CEREMA) # présentation des données sur https://www.data.gouv.fr/fr/datasets/logements-vacants-du-parc-prive-par-anciennete-de-vacance-par-commune-et-par-epci/ url <- "https://www.data.gouv.fr/fr/datasets/r/ed0aa123-6afa-49fe-8e35-797a30a44c43" download.file(url, destfile = "extdata/logements-vacants-du-parc-prive-au-01012021-lovac-.xlsx", mode = "wb") lgt_vac_prv <- read_xlsx("extdata/logements-vacants-du-parc-prive-au-01012021-lovac-.xlsx", sheet = 1) datatable(head(lgt_vac_prv), options = list(dom = 't')) 4.3 Lire des données disponibles sur le web via API De plus en plus de mise à disposition de données, se font via des API (Application Programming Interface). Une API correspond à un protocole de communication entre un logiciel fournisseur et un logiciel utilisateur. L’utilisateur doit suivre une série de méthodes définies par le fournisseur. Par rapport au téléchargement de fichier via download.file(), on peut ne récupérer qu’une partie du jeu de données. L’autre avantage est la stabilité des url de téléchargement. En savoir plus sur les API : https://thinkr.fr/les-api-un-enfer/. Connaître les API de l’Etat : https://api.gouv.fr/rechercher-api Plusieurs solutions sont disponibles pour lire des données au travers d’une API dans R : tester l’API sur votre navigateur, et une fois que l’URL de requête est construite, lire le résultat JSON depuis R -> cf exemple URSSAF utiliser en complément le package {httr} qui simplifie le recours aux API dans R -> exemple ODRE utiliser un package wrapper, c’est à dire ‘enrobant’, dédié à une API spécifique, qui simplifie encore plus l’utilisation de l’API et allège l’écriture -> exemple {Didor} du ministère et {rsdmx} de l’INSEE. 4.3.1 Exemple de recours à l’API opendatasoft en utilisant l’API de l’URSSAF ou de l’ODRE Opendatasoft est une solution de plateforme opendata comprenant un catalogue, une visualisation des tables, une valorisation graphiques ou cartographiques du jeu de données diffusé et une API d’accès. Cette solution est utilisée par de nombreux acteurs publics (Urssaf, énergéticiens, collectivités, Groupe La Poste…). Chaque partie (catalogue, métadonnées, enregistrements…) fait l’objet d’une URL d’API distincte, en voici deux exemples. 1er exemple données URSSAF des effectifs salariés et de masse salariale du secteur privé par région : library(jsonlite) url_urssaf_fr <- "https://open.urssaf.fr/api/records/1.0/search/?dataset=effectifs-salaries-et-masse-salariale-du-secteur-prive-par-region-x-na38&q=&rows=10000&facet=grand_secteur_d_activite&facet=secteur_na28i&facet=annee&facet=trimestre&refine.region=Pays+de+la+Loire" reponse_urssaf_fr <- fromJSON(url_urssaf_fr) urssaf_fr <- reponse_urssaf_fr$records$fields datatable(urssaf_fr) La récupération des métadonnées d’un jeu de données se fait avec une autre url, en voici un exemple à partir de la plateforme opendata des réseaux d’énergie (ODRE) # Description du jeu de données dataset_url <- paste0("https://opendata.reseaux-energies.fr/api/dataset/1.0/prod-region-annuelle-enr") metadata <- httr::GET(dataset_url) %>% httr::content("text") %>% jsonlite::fromJSON(flatten = TRUE) attributs <- metadata$fields datatable(attributs) # Enregistrements data_url <-"https://opendata.reseaux-energies.fr/api/records/1.0/search/?dataset=prod-region-annuelle-enr&q=&rows=50&facet=code_insee_region&refine.code_insee_region=52" prod_annuelle_enr <- jsonlite::fromJSON(data_url)$records$fields 4.3.2 Packages R d’interrogation d’API Pour faciliter l’utilisation de leur API par les utilisateurs de R, certains fournisseurs propose un package R pour se brancher à leur données. Le support vous propose deux exemples (INSEE et CGDD), mais il en existe de nombreux ! Pour trouver des packages R qui facilitent l’utilisation d’API françaises, rdv sur : https://github.com/frrrenchies/frrrenchies#package-packages-package 4.3.2.1 Lire des données du webservice Insee L’Insee met à disposition un webservice d’accès (API) à des données de référence sous le format sdmx. Le package {rsdmx} permet de se connecter directement à ces données. Deux approches sont possibles. La première permet d’accéder à une série particulière. url <- "https://bdm.insee.fr/series/sdmx/data/SERIES_BDM/001564471" datainsee <- as.data.frame(readSDMX(url)) # Encoding(levels(datainsee$TITLE_FR)) <- "UTF-8" Cette approche permet également de télécharger plusieurs séries en une seule requête. Par exemple : nous téléchargeons l’ensemble des données sur les créations et défaillances d’entreprises pour les secteurs de la construction et de l’immobilier sur les Pays de la Loire. url <- "https://bdm.insee.fr/series/sdmx/data/SERIES_BDM/001564471+001564503+001564799+001564823+001582441+001582578+001582597+001582745+001656155+001656161+001655989+001655995" datainsee <- as.data.frame(readSDMX(url)) L’autre approche permet de télécharger un ensemble de données d’une thématique appelé dataflow. Ici, par exemple, on télécharge l’ensemble des données relatives à la construction neuve : url <- "https://bdm.insee.fr/series/sdmx/data/CONSTRUCTION-LOGEMENTS" datainsee <- as.data.frame(readSDMX(url)) 4.3.2.2 Interroger le catalogue DiDo du CGDD et lire les jeux de données grâce à {didor} {didor} est un package R conçu pour explorer et accéder aux données publiées par le SDES au CGDD sur DIDO. Le package {didor} s’installe depuis GitHub : install.packages("devtools") devtools::install_github("mtes-mct/didor") Voici un exemple d’utilisation pour récupérer les données de consommation de produits pétroliers dans les DROM : # devtools::install_github("mtes-mct/didor") library(didor) library(tidyverse) result <- datasets() %>% dido_search("produit-petrolier") %>% datafiles() %>% dido_search("drom") %>% get_data() knitr::kable(head(result)) Tutoriel complet : https://mtes-mct.github.io/didor/articles/premiers_pas.html 4.4 Lire des fichiers avec une dimension spatiale Le package {sf} (pour simple feature) permet d’importer dans R un fichier ayant une dimension spatiale. Après importation, le fichier est un dataframe avec une variable d’un type nouveau : la géométrie. Deux exemples ici pour lire des données au format shape et geojson. Carte_com_Mayotte <- st_read(dsn = "extdata", layer = "com_mayotte") ## Reading layer `com_mayotte' from data source ## `/__w/parcours_r_socle_preparation_des_donnees/parcours_r_socle_preparation_des_donnees/extdata' ## using driver `ESRI Shapefile' ## Simple feature collection with 17 features and 11 fields ## Geometry type: MULTIPOLYGON ## Dimension: XY ## Bounding box: xmin: 501990.5 ymin: 8562261 xmax: 532559.5 ymax: 8603052 ## Projected CRS: RGM04_UTM_zone_38S plot(Carte_com_Mayotte) communes2017 <- st_read(dsn = "extdata/communes2017.geojson") ## Reading layer `communes2017' from data source ## `/__w/parcours_r_socle_preparation_des_donnees/parcours_r_socle_preparation_des_donnees/extdata/communes2017.geojson' ## using driver `GeoJSON' ## Simple feature collection with 1281 features and 10 fields ## Geometry type: MULTIPOLYGON ## Dimension: XY ## Bounding box: xmin: 280973 ymin: 6582762 xmax: 545050 ymax: 6834665 ## Projected CRS: RGF93 / Lambert-93 plot(communes2017) Le package {sf} contient l’ensemble des fonctions permettant des manipulations sur fichiers géomatiques. On ne traitera pas ici de toutes ces fonctions en détail, se référer pour cela à la documentation du package ou suivre le module 7 du parcours de formation à R du ministère. A noter que {sf} étant complètement compatible avec les packages du tidyverse, la géométrie se conçoit comme une donnée comme une autre, sur laquelle par exemple on peut réaliser des agrégations. On peut également lire des couches directement depuis le web : st_read("https://france-geojson.gregoiredavid.fr/repo/regions.geojson") %>% filter(code > "10") %>% select(code) %>% plot() {sf} propose de lire toutes sortes de données spatiales. sf::st_drivers() ## name ## PCIDSK PCIDSK ## netCDF netCDF ## PDS4 PDS4 ## JP2OpenJPEG JP2OpenJPEG ## PDF PDF ## MBTiles MBTiles ## EEDA EEDA ## ESRI Shapefile ESRI Shapefile ## MapInfo File MapInfo File ## UK .NTF UK .NTF ## OGR_SDTS OGR_SDTS ## S57 S57 ## DGN DGN ## OGR_VRT OGR_VRT ## REC REC ## Memory Memory ## BNA BNA ## CSV CSV ## NAS NAS ## GML GML ## GPX GPX ## LIBKML LIBKML ## KML KML ## GeoJSON GeoJSON ## GeoJSONSeq GeoJSONSeq ## ESRIJSON ESRIJSON ## TopoJSON TopoJSON ## Interlis 1 Interlis 1 ## Interlis 2 Interlis 2 ## OGR_GMT OGR_GMT ## GPKG GPKG ## SQLite SQLite ## OGR_DODS OGR_DODS ## ODBC ODBC ## WAsP WAsP ## PGeo PGeo ## MSSQLSpatial MSSQLSpatial ## OGR_OGDI OGR_OGDI ## PostgreSQL PostgreSQL ## MySQL MySQL ## OpenFileGDB OpenFileGDB ## XPlane XPlane ## DXF DXF ## CAD CAD ## Geoconcept Geoconcept ## GeoRSS GeoRSS ## GPSTrackMaker GPSTrackMaker ## VFK VFK ## PGDUMP PGDUMP ## OSM OSM ## GPSBabel GPSBabel ## SUA SUA ## OpenAir OpenAir ## OGR_PDS OGR_PDS ## WFS WFS ## WFS3 WFS3 ## SOSI SOSI ## HTF HTF ## AeronavFAA AeronavFAA ## Geomedia Geomedia ## EDIGEO EDIGEO ## GFT GFT ## SVG SVG ## CouchDB CouchDB ## Cloudant Cloudant ## Idrisi Idrisi ## ARCGEN ARCGEN ## SEGUKOOA SEGUKOOA ## SEGY SEGY ## XLS XLS ## ODS ODS ## XLSX XLSX ## ElasticSearch ElasticSearch ## Walk Walk ## Carto Carto ## AmigoCloud AmigoCloud ## SXF SXF ## Selafin Selafin ## JML JML ## PLSCENES PLSCENES ## CSW CSW ## VDV VDV ## GMLAS GMLAS ## MVT MVT ## TIGER TIGER ## AVCBin AVCBin ## AVCE00 AVCE00 ## NGW NGW ## HTTP HTTP ## long_name ## PCIDSK PCIDSK Database File ## netCDF Network Common Data Format ## PDS4 NASA Planetary Data System 4 ## JP2OpenJPEG JPEG-2000 driver based on OpenJPEG library ## PDF Geospatial PDF ## MBTiles MBTiles ## EEDA Earth Engine Data API ## ESRI Shapefile ESRI Shapefile ## MapInfo File MapInfo File ## UK .NTF UK .NTF ## OGR_SDTS SDTS ## S57 IHO S-57 (ENC) ## DGN Microstation DGN ## OGR_VRT VRT - Virtual Datasource ## REC EPIInfo .REC ## Memory Memory ## BNA Atlas BNA ## CSV Comma Separated Value (.csv) ## NAS NAS - ALKIS ## GML Geography Markup Language (GML) ## GPX GPX ## LIBKML Keyhole Markup Language (LIBKML) ## KML Keyhole Markup Language (KML) ## GeoJSON GeoJSON ## GeoJSONSeq GeoJSON Sequence ## ESRIJSON ESRIJSON ## TopoJSON TopoJSON ## Interlis 1 Interlis 1 ## Interlis 2 Interlis 2 ## OGR_GMT GMT ASCII Vectors (.gmt) ## GPKG GeoPackage ## SQLite SQLite / Spatialite ## OGR_DODS OGR_DODS ## ODBC ODBC ## WAsP WAsP .map format ## PGeo ESRI Personal GeoDatabase ## MSSQLSpatial Microsoft SQL Server Spatial Database ## OGR_OGDI OGDI Vectors (VPF, VMAP, DCW) ## PostgreSQL PostgreSQL/PostGIS ## MySQL MySQL ## OpenFileGDB ESRI FileGDB ## XPlane X-Plane/Flightgear aeronautical data ## DXF AutoCAD DXF ## CAD AutoCAD Driver ## Geoconcept Geoconcept ## GeoRSS GeoRSS ## GPSTrackMaker GPSTrackMaker ## VFK Czech Cadastral Exchange Data Format ## PGDUMP PostgreSQL SQL dump ## OSM OpenStreetMap XML and PBF ## GPSBabel GPSBabel ## SUA Tim Newport-Peace's Special Use Airspace Format ## OpenAir OpenAir ## OGR_PDS Planetary Data Systems TABLE ## WFS OGC WFS (Web Feature Service) ## WFS3 OGC WFS 3 client (Web Feature Service) ## SOSI Norwegian SOSI Standard ## HTF Hydrographic Transfer Vector ## AeronavFAA Aeronav FAA ## Geomedia Geomedia .mdb ## EDIGEO French EDIGEO exchange format ## GFT Google Fusion Tables ## SVG Scalable Vector Graphics ## CouchDB CouchDB / GeoCouch ## Cloudant Cloudant / CouchDB ## Idrisi Idrisi Vector (.vct) ## ARCGEN Arc/Info Generate ## SEGUKOOA SEG-P1 / UKOOA P1/90 ## SEGY SEG-Y ## XLS MS Excel format ## ODS Open Document/ LibreOffice / OpenOffice Spreadsheet ## XLSX MS Office Open XML spreadsheet ## ElasticSearch Elastic Search ## Walk Walk ## Carto Carto ## AmigoCloud AmigoCloud ## SXF Storage and eXchange Format ## Selafin Selafin ## JML OpenJUMP JML ## PLSCENES Planet Labs Scenes API ## CSW OGC CSW (Catalog Service for the Web) ## VDV VDV-451/VDV-452/INTREST Data Format ## GMLAS Geography Markup Language (GML) driven by application schemas ## MVT Mapbox Vector Tiles ## TIGER U.S. Census TIGER/Line ## AVCBin Arc/Info Binary Coverage ## AVCE00 Arc/Info E00 (ASCII) Coverage ## NGW NextGIS Web ## HTTP HTTP Fetching Wrapper ## write copy is_raster is_vector vsi ## PCIDSK TRUE FALSE TRUE TRUE TRUE ## netCDF TRUE TRUE TRUE TRUE TRUE ## PDS4 TRUE TRUE TRUE TRUE TRUE ## JP2OpenJPEG FALSE TRUE TRUE TRUE TRUE ## PDF TRUE TRUE TRUE TRUE TRUE ## MBTiles TRUE TRUE TRUE TRUE TRUE ## EEDA FALSE FALSE FALSE TRUE FALSE ## ESRI Shapefile TRUE FALSE FALSE TRUE TRUE ## MapInfo File TRUE FALSE FALSE TRUE TRUE ## UK .NTF FALSE FALSE FALSE TRUE TRUE ## OGR_SDTS FALSE FALSE FALSE TRUE TRUE ## S57 TRUE FALSE FALSE TRUE TRUE ## DGN TRUE FALSE FALSE TRUE TRUE ## OGR_VRT FALSE FALSE FALSE TRUE TRUE ## REC FALSE FALSE FALSE TRUE FALSE ## Memory TRUE FALSE FALSE TRUE FALSE ## BNA TRUE FALSE FALSE TRUE TRUE ## CSV TRUE FALSE FALSE TRUE TRUE ## NAS FALSE FALSE FALSE TRUE TRUE ## GML TRUE FALSE FALSE TRUE TRUE ## GPX TRUE FALSE FALSE TRUE TRUE ## LIBKML TRUE FALSE FALSE TRUE TRUE ## KML TRUE FALSE FALSE TRUE TRUE ## GeoJSON TRUE FALSE FALSE TRUE TRUE ## GeoJSONSeq TRUE FALSE FALSE TRUE TRUE ## ESRIJSON FALSE FALSE FALSE TRUE TRUE ## TopoJSON FALSE FALSE FALSE TRUE TRUE ## Interlis 1 TRUE FALSE FALSE TRUE TRUE ## Interlis 2 TRUE FALSE FALSE TRUE TRUE ## OGR_GMT TRUE FALSE FALSE TRUE TRUE ## GPKG TRUE TRUE TRUE TRUE TRUE ## SQLite TRUE FALSE FALSE TRUE TRUE ## OGR_DODS FALSE FALSE FALSE TRUE FALSE ## ODBC TRUE FALSE FALSE TRUE FALSE ## WAsP TRUE FALSE FALSE TRUE TRUE ## PGeo FALSE FALSE FALSE TRUE FALSE ## MSSQLSpatial TRUE FALSE FALSE TRUE FALSE ## OGR_OGDI FALSE FALSE FALSE TRUE FALSE ## PostgreSQL TRUE FALSE FALSE TRUE FALSE ## MySQL TRUE FALSE FALSE TRUE FALSE ## OpenFileGDB FALSE FALSE FALSE TRUE TRUE ## XPlane FALSE FALSE FALSE TRUE TRUE ## DXF TRUE FALSE FALSE TRUE TRUE ## CAD FALSE FALSE TRUE TRUE TRUE ## Geoconcept TRUE FALSE FALSE TRUE TRUE ## GeoRSS TRUE FALSE FALSE TRUE TRUE ## GPSTrackMaker TRUE FALSE FALSE TRUE TRUE ## VFK FALSE FALSE FALSE TRUE FALSE ## PGDUMP TRUE FALSE FALSE TRUE TRUE ## OSM FALSE FALSE FALSE TRUE TRUE ## GPSBabel TRUE FALSE FALSE TRUE FALSE ## SUA FALSE FALSE FALSE TRUE TRUE ## OpenAir FALSE FALSE FALSE TRUE TRUE ## OGR_PDS FALSE FALSE FALSE TRUE TRUE ## WFS FALSE FALSE FALSE TRUE TRUE ## WFS3 FALSE FALSE FALSE TRUE FALSE ## SOSI FALSE FALSE FALSE TRUE FALSE ## HTF FALSE FALSE FALSE TRUE TRUE ## AeronavFAA FALSE FALSE FALSE TRUE TRUE ## Geomedia FALSE FALSE FALSE TRUE FALSE ## EDIGEO FALSE FALSE FALSE TRUE TRUE ## GFT TRUE FALSE FALSE TRUE FALSE ## SVG FALSE FALSE FALSE TRUE TRUE ## CouchDB TRUE FALSE FALSE TRUE FALSE ## Cloudant TRUE FALSE FALSE TRUE FALSE ## Idrisi FALSE FALSE FALSE TRUE TRUE ## ARCGEN FALSE FALSE FALSE TRUE TRUE ## SEGUKOOA FALSE FALSE FALSE TRUE TRUE ## SEGY FALSE FALSE FALSE TRUE TRUE ## XLS FALSE FALSE FALSE TRUE FALSE ## ODS TRUE FALSE FALSE TRUE TRUE ## XLSX TRUE FALSE FALSE TRUE TRUE ## ElasticSearch TRUE FALSE FALSE TRUE FALSE ## Walk FALSE FALSE FALSE TRUE FALSE ## Carto TRUE FALSE FALSE TRUE FALSE ## AmigoCloud TRUE FALSE FALSE TRUE FALSE ## SXF FALSE FALSE FALSE TRUE TRUE ## Selafin TRUE FALSE FALSE TRUE TRUE ## JML TRUE FALSE FALSE TRUE TRUE ## PLSCENES FALSE FALSE TRUE TRUE FALSE ## CSW FALSE FALSE FALSE TRUE FALSE ## VDV TRUE FALSE FALSE TRUE TRUE ## GMLAS FALSE TRUE FALSE TRUE TRUE ## MVT TRUE FALSE FALSE TRUE TRUE ## TIGER TRUE FALSE FALSE TRUE TRUE ## AVCBin FALSE FALSE FALSE TRUE TRUE ## AVCE00 FALSE FALSE FALSE TRUE TRUE ## NGW TRUE TRUE TRUE TRUE FALSE ## HTTP FALSE FALSE TRUE TRUE FALSE Il comprend notamment un driver pour lire les flux WFS, émis par nos plateforme de données géographiques. Voici un exemple issu de SIGloire : crte <- sf::st_read(dsn = 'https://datacarto.sigloire.fr/wfs?REQUEST=getCapabilities&service=WFS&VERSION=2.0.0', layer = "ms:r_portrait_crte_r52") crte %>% select(nom_territ) %>% plot On indique au niveau du paramètre dsn l’url du webservice WFS de la plateforme et au niveau du parametre layer le nom de la couche. Pour aller plus loin dans l’exploitation des flux WFS dans R : https://inbo.github.io/tutorials/tutorials/spatial_wfs_services/. 4.5 Lire des données sous PostgreSQL Deux approches possibles pour utiliser des données stockées dans une base de données PostgreSQL. Importer toutes ces données dans l’environnement R se connecter à ces données (sans les charger en mémoire vive) et utiliser un interpréteur permettant de traduire du code R comme une requête SQL. 4.5.1 Lire des données sous PostgreSQL : première approche Le package {DBI} est fréquemment utilisé pour connecter des bases de données à R. On ouvre une connexion en déclarant les informations liées à la base (adresse, identifiants..) et en choisissant le driver de connexion. #Définition du driver drv <- dbDriver("PostgreSQL") #Définition de la base de données con <- dbConnect(drv, dbname = "dbname", host = "ip", port = numero_du_port, user = "user_name", password = "pwd") #Spécification de l'encodage, obligatoire avec Windows postgresqlpqExec(con, "SET client_encoding = 'windows-1252'") #Téléchargement de la table analyse du schéma pesticide parametre <- dbGetQuery(con, "SELECT * FROM pesticides.parametre") #Téléchargement de données avec dimension spatiale via la fonction st_read du package simple feature station = st_read(con, query = "SELECT * FROM pesticides.station") station = st_read(dsn = con, layer = c(schema = 'pesticides', table = 'station')) On voit que pour importer notre table analyse, on a simplement lancé une requête SQL. Pour obtenir un résultat qui préserve le caractère spatial de notre jeu de données, il faut changer de fonction de lecture. Un package, encore expérimental, de la DREAL Pays de la Loire, {datalibaba} simplifie l’écriture des instructions de lecture/écriture de données vers ou depuis un SGBD Postgresql/postgis. Il propose de stocker vos identifiants de connexion dans vos variable d’environnement afin d’en préserver la confidentialité et de vous éviter de les réécrire dans chaque script. L’utilisateur n’a plus à se préoccuper du driver de connexion ni de la fonction de lecture. Les instruction précédentes deviennent : remotes::install_gitlab('dreal-datalab/datalibaba') library(datalibaba) parametre <- importer_data(table = "parametre", schema = "pesticides") station <- importer_data(table = "station", schema = "pesticides") 4.5.2 Lire des données sous PostgreSQL : seconde approche #définition du driver drv <- dbDriver("PostgreSQL") #définition de la base de données con <- dbConnect(drv, dbname = "dbname", host = "ip", port = numero_du_port, user = "user_name", password = "pwd") #spécification de l'encodage, obligatoire avec windows postgresqlpqExec(con, "SET client_encoding = 'windows-1252'") #téléchargement de la table analyse du schéma pesticide analyse_db <- tbl(con, in_schema("pesticides", "analyse")) Ici la table analyse n’est pas chargée dans l’environnement R, R s’est juste connecté à la base de données. On peut réaliser des opérations sur la table analyse avec du code R très simplement. Par exemple pour filtrer sur les analyses relatives au Glyphosate : analyse_db <- filter(analyse_db, code_parametre == 1506) Attention, ce code ne touche pas la base de donnée, il n’est pas exécuté. Pour l’exécuter, il faut par exemple afficher la table. analyse_db Même une fois le code exécuté, cette base n’est pas encore un dataframe. Pour importer la table, on utilise la fonction collect() analyse_db <- collect(analyse_db) Cette approche est à conseiller sur d’importantes bases de données, et sans dimension spatiale, car {dbplyr} ne sait pas encore lire facilement ce type de variable. 4.6 Lire des fichiers au format parquet Apache Parquet est un choix de plus en plus populaire pour le stockage et l’analyse de données. C’est un format binaire optimisé pour réduire la taille des fichiers et offrir une excellente vitesse de lecture, surtout si on souhaite accéder à un jeu de données en ne lisant que quelques colonnes. Egalement, il est lisible dans de nombreux langages et prévoit, un peu comme avec une base de données PostgreSQL, qu’on exprime une requête de lecture pour limiter la montée des données en RAM au minimum nécessaire. Enfin on peut grouper les lignes lors un export parquet et réaliser une partition du fichier, par exemple par département ou par région, dans l’idée que certains utilisateurs n’ont pas besoin d’accéder à tout, pour encore accélérer la lecture. Bref, cela va devenir un must dans la diffusion de données millésimées. La manière la plus courante de lire et d’écrire des données au format Parquet avec R est d’utiliser le package {Arrow}, et ses les fonctions read_parquet() et write_parquet(). Le package parquetize permet de convertir en masse des jeux de données depuis SAS, Stata, sqlite ou JSON vers parquet. library(arrow) datatable(head(iris)) tf <- tempfile() write_parquet(iris, tf) df <- read_parquet(tf, col_select = starts_with("Se")) datatable(head(df)) Pour les données spatiales, le format geoparquet est désormais opérationnel (v1 en décembre 2022). Deux packages ont été développés pour l’utilisation de geoparquet avec R : {sfarrow} sur le CRAN et {geoparquet} en phase de développement actif sur github. S’il est très efficace pour l’analyse de données, Parquet est en revanche peu adapté à l’ajout de données en continu ou à la modification fréquente de données existantes. Pour cette utilisation, il faut privilégier un système de gestion de base de données comme par exemple PostgreSQL. Pour en savoir plus sur ce format promis à un bel avenir au ministère : nous vous recommandons la fiche utilitR de l’INSEE dédiée à la question. "],["manipuler-des-données.html", "Chapitre 5 Manipuler des données 5.1 Les principes des fonctions de {dplyr} 5.2 Présentation des données 5.3 Chargement des données 5.4 Les verbes clefs de {dplyr} pour manipuler une table 5.5 La boîte à outils pour créer et modifier des variables avec R 5.6 Agréger des données : summarise() 5.7 Agréger des données par dimension : group_by() 5.8 Le pipe 5.9 La magie des opérations groupées 5.10 Les armes non conventionnelles de la préparation des donnéees", " Chapitre 5 Manipuler des données 5.1 Les principes des fonctions de {dplyr} Le but de {dplyr} est d’identifier et de rassembler dans un seul package les outils de manipulation de données les plus importantes pour l’analyse des données. Ce package rassemble donc des fonctions correspondant à un ensemble d’opérations élémentaires (ou verbes) qui permettent de : Sélectionner un ensemble de variables : select() Sélectionner un ensemble de lignes : filter() Ajouter/modifier/renommer des variables : mutate() ou rename() Produire des statistiques agrégées sur les dimensions d’une table : summarise() Trier une table : arrange() Manipuler plusieurs tables : left_join(), right_join(), full_join(), inner_join()… D’appliquer cela sur des données, quel que soit leur format : dataframes, data.table, couche spatiale, base de données sql, big data… D’appliquer cela en articulation avec group_by() qui change la façon d’interpréter chaque fonction : d’une interprétation globale sur l’ensemble d’une table, on passe alors à une approche groupe par groupe : chaque groupe étant défini par un ensemble des modalités des variables définies dans l’instruction group_by(). 5.2 Présentation des données On va travailler sur ce module principalement à partir des données sitadel en date réelle estimée (permis de construire) et à partir des données de qualité des eaux de surface. 5.3 Chargement des données load(file = "extdata/FormationPreparationDesDonnees.RData") 5.4 Les verbes clefs de {dplyr} pour manipuler une table 5.4.1 Sélectionner des variables : select() Nous allons ici sélectionner un ensemble de variables de la table des prélèvements. prelevementb <- select( prelevement, date_prelevement, code_prelevement, code_reseau, code_station ) datatable(head(prelevementb)) prelevementb <- select(prelevement, -code_support) names(prelevementb) ## [1] "code_prelevement" "code_intervenant" "code_reseau" "code_station" ## [5] "date_prelevement" select() possède ce qu’on appelle des helpers qui permettent de gagner du temps dans l’écriture de notre sélection. A partir du moment où les conventions de nommage sont correctement effectuées, cela permet de gagner également en reproductibilité d’une année sur l’autre. Exemple : sélectionner toutes les variables qui commencent par “code_” : prelevementb <- select(prelevement, starts_with("code_")) Exemple : sélectionner les variables dont les noms sont contenus dans un vecteur de chaînes de caractères : mes_variables <- c("code_prelevement", "code_intervenant", "code_reseau", "date_prelevement") prelevementb <- select(prelevement, one_of(mes_variables)) 5.4.2 Trier une table : arrange() prelevementb <- arrange(prelevementb, date_prelevement) 5.4.3 Renommer une variable : rename() prelevementb <- rename(prelevementb, date_p = date_prelevement) On peut aussi directement renommer une variable dans l’opération select() prelevementb <- select(prelevement, date_p = date_prelevement, code_prelevement, code_reseau, code_station) 5.4.4 Filtrer une table : filter() On va ici récupérer les analyses produites par l’ARS ars <- filter(prelevement, code_reseau == "ARS") L’exemple ci-dessus n’exerce un filtre que sur une condition unique. Pour des conditions cumulatives (toutes les conditions doivent être remplies), le \"&\" ou la \",\" ars <- filter(prelevement, code_reseau == "ARS", code_intervenant == "44") Pour des conditions non cumulatives (au moins une des conditions doit être remplie), le “|” ars <- filter(prelevement, code_reseau == "ARS" | code_reseau == "FREDON") Si une condition non cumulative s’applique sur une même variable, privilégier un test de sélection dans une liste avec le %in% ars <- filter(prelevement, code_reseau %in% c("ARS", "FREDON")) Pour sélectionner des observations qui ne répondent pas à la condition, le ! (la négation d’un test) Toutes les observations ayant été réalisées par un autre réseau que l’ARS : non_ars <- filter(prelevement, code_reseau != "ARS") Toutes les observations ayant été réalisées par un autre réseau que l’ARS ou FREDON : ni_ars_ni_fredon <- filter(prelevement, !(code_reseau %in% c("ARS", "FREDON"))) 5.4.5 Modifier/ajouter une variable : mutate() mutate() est le verbe qui permet la transformation d’une variable existante ou la création d’une nouvelle variable dans le jeu de données. Création de nouvelles variables : prelevementb <- mutate(prelevementb, code_prelevement_caract = as.character(code_prelevement), code_reseau_fact = as.factor(code_reseau) ) Modification de variables existantes : prelevementb <- mutate(prelevementb, code_prelevement = as.character(code_prelevement), code_reseau = as.factor(code_reseau) ) mutate() possède une variante, transmute(), qui fonctionne de la même façon, mais ne conserve que les variables modifiées ou créées par le verbe. 5.4.6 Extraire un vecteur : pull() pull() permet d’extraire sous forme de vecteur une variable d’un dataframe. stations_de_la_table_prelevement <- pull(prelevement, code_station) stations_de_la_table_prelevement <- unique(stations_de_la_table_prelevement) 5.5 La boîte à outils pour créer et modifier des variables avec R 5.5.1 Manipuler des variables numériques Vous pouvez utiliser beaucoup de fonctions pour créer des variables avec mutate() : les opérations arithmétiques : +,-,*,/,^ ; arithmétique modulaire : %/% (division entière) et %% (le reste), où x == y * (x %/% y) + (x %% y) ; logarithmes : log(), log2(), log10() ; navigations entre les lignes : lead() et lag() qui permettent d’avoir accès à la valeur suivante et précédente d’une variable. a <- data.frame(x=sample(1:10)) b <- mutate(a, lagx = lag(x), leadx = lead(x), lag2x = lag(x, n = 2), lead2x = lead(x, n = 2)) datatable(b) opérations cumulatives ou glissantes : R fournit des fonctions pour obtenir des opérations cumulatives les somme, produit, minimum et maximum cumulés, dplyr fournit l’équivalent pour les moyennes : cumsum(), cumprod(), cummin(), cummax(), cummean() Pour appliquer des opérations glissantes, on peut soit créer l’opération avec l’instruction lag(), soit exploiter le package RcppRoll qui permet d’exploiter des fonctions prédéfinies. Exemple de somme glissante sur un pas de 2 observations. a <- data.frame(x = sample(1:10)) b <- mutate(a, cumsumx = cumsum(x), rollsumrx = roll_sumr(x, n = 2)) datatable(b) Attention aux différences entre roll_sum() et roll_sumr(). Contrairement à roll_sum(), la fonction roll_sumr() fait en sorte d’obtenir un vecteur de même dimension que l’entrée : a$x ## [1] 3 10 6 2 8 9 5 1 7 4 rollsumrx <- roll_sumr(a$x, n=2) rollsumx <- roll_sum(a$x, n=2) length(rollsumrx) == length(a$x) ## [1] TRUE length(rollsumx) == length(a$x) ## [1] FALSE Aussi dans le cadre d’opérations sur les dataframes, roll_sum() ne fonctionnera pas. b <- mutate(a, cumsumx = cumsum(x), rollsumx = roll_sum(x, n=2)) Comparaisons logiques : <, <=, >, >=, != Rangs : min_rank() devrait être la plus utile, il existe aussi notamment row_number(), dense_rank(), percent_rank(), cume_dist(), ntile(). coalesce(x, y) : permet de remplacer les valeurs manquantes de x par celle de y variable = ifelse(condition(x), valeursioui, valeursinon) permet d’affecter valeursi ou valeursinon à variable en fonction du fait que x répond à condition. Exemple : création d’une variable résultat pour savoir si les résultats de nos analyses sont bons, ou non. analyseb <- mutate(analyse, resultat_ok = ifelse(code_remarque %in% c(1, 2, 7, 10), yes = TRUE, no = FALSE)) qui peut se résumer, lorsque yes = TRUE et no = FALSE, à : analyseb <- mutate(analyse, resultat_ok = code_remarque %in% c(1, 2, 7, 10)) case_when() permet d’étendre la logique de ifelse() à des cas plus complexes. Les conditions mises dans un case_when() ne sont pas exclusives. De ce fait, il faut pouvoir déterminer l’ordre d’évaluation des conditions qui y sont posées. Cet ordre s’effectue de bas en haut, c’est à dire que la dernière condition évaluée (celle qui primera sur toutes les autres) sera la première à écrire. Exemple: On va ici calculer des seuils fictifs sur les analyses. analyseb <- mutate(analyse, classe_resultat_analyse = case_when( resultat_analyse == 0 ~ "1", resultat_analyse <= 0.001 ~ "2", resultat_analyse <= 0.01 ~ "3", resultat_analyse <= 0.1 ~ "4", resultat_analyse > 0.1 ~ "5", TRUE ~ "" )) 5.5.2 Exercice 1 : Les données mensuelles sitadel cf. package d’exercices {savoirfR} À partir du fichier sitadel de février 2017 (ROES_201702.xls), produire un dataframe ‘sit_pdl_ind’ contenant pour la région Pays-de-la-Loire (code région 52), pour chaque mois et pour les logements individuels (définis par la somme des logements individuels purs et individuels groupés : i_AUT = ip_AUT + ig_AUT) : le cumul des autorisations sur 12 mois glissants (i_AUT_cum12), le taux d’évolution du cumul sur 12 mois (i_AUT_cum_evo, en %), la part de ce cumul dans celui de l’ensemble des logements autorisés (log_AUT), en pourcentage. Résultat attendu : solution sans le pipe (apercu des premières lignes) %>% ## # A tibble: 6 × 12 ## date REG log_AUT ip_AUT ig_AUT colres_AUT i_AUT i_AUT_cum12 ## <chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> ## 1 200001 52 1789 1266 245 278 1511 NA ## 2 200002 52 2022 1529 175 318 1704 NA ## 3 200003 52 2270 1466 205 599 1671 NA ## 4 200004 52 2040 1237 162 641 1399 NA ## 5 200005 52 2361 1357 357 647 1714 NA ## 6 200006 52 2504 1436 250 818 1686 NA ## # ℹ 4 more variables: i_AUT_cum12_lag12 <dbl>, i_AUT_cum_evo <dbl>, ## # log_AUT_cum12 <dbl>, part_i_AU <dbl> solution avec le pipe (apercu des premières lignes) %>% ## # A tibble: 6 × 12 ## date REG log_AUT ip_AUT ig_AUT colres_AUT i_AUT i_AUT_cum12 ## <chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> ## 1 200001 52 1789 1266 245 278 1511 NA ## 2 200002 52 2022 1529 175 318 1704 NA ## 3 200003 52 2270 1466 205 599 1671 NA ## 4 200004 52 2040 1237 162 641 1399 NA ## 5 200005 52 2361 1357 357 647 1714 NA ## 6 200006 52 2504 1436 250 818 1686 NA ## # ℹ 4 more variables: i_AUT_cum12_lag12 <dbl>, i_AUT_cum_evo <dbl>, ## # log_AUT_cum12 <dbl>, part_i_AU <dbl> 5.5.3 Manipuler des dates Parmi l’ensemble des manipulations de variables, celle des dates et des heures est toujours une affaire complexe. Le framework tidyverse propose le package {lubridate} qui permet de gérer ces informations de façon cohérente. gestion des dates : dmy("jeudi 21 novembre 2020") dmy("21112020") ymd("20201121") gestion des dates/heures : dmy_hms("mardi 21 novembre 2020 9:30:00") now() combien de jours avant Noël ? annee_en_cours <- year(today()) prochain_noel <- paste("25 décembre", annee_en_cours) prochain_noel dmy(prochain_noel) - today() le jour de la semaine d’une date : wday(dmy("19012038"), label = TRUE) Les fonctions make_date() et make_datetime() vous permettent de transformer un ensemble de variables en un format date ou date - heure. C’est par exemple utile lorsque l’on a des variables séparées pour l’année, le mois et le jour. 5.5.3.1 Exercice 2 : les dates Convertir les colonnes de la table exercice au format date (quand c’est pertinent). La table exercice est issue de FormationPreparationDesDonnees.RData. Résultat attendu : ## Rows: 153,497 ## Columns: 22 ## $ code_analyse <int> 5186581, 280131, 1576225, 799894, 472800, 27671… ## $ code_laboratoire <dbl> NA, 292, NA, NA, 292, NA, NA, NA, NA, NA, NA, N… ## $ code_prelevement <int> 37593, 7715, 15517, 9566, 8332, 26792, 35625, 1… ## $ code_parametre <dbl> 1216, 1668, 1185, 1217, 1907, 1945, 1673, 1234,… ## $ code_fraction_analysee <int> 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,… ## $ resultat_analyse <dbl> 0.007, 0.050, 0.040, 0.050, 0.260, 0.020, 0.010… ## $ code_remarque <int> 10, 2, 2, 2, 1, 10, 10, 10, 10, 10, 10, 10, 2, … ## $ limite_detection <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,… ## $ limite_quantification <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,… ## $ code_intervenant <fct> NA, 104, NA, NA, 104, NA, NA, 53, NA, 44, 49, 4… ## $ code_reseau <fct> OSUR, OSUR, FREDON, OSUR, OSUR, OSUR, OSUR, ARS… ## $ code_station <chr> "04153800", "04130000", "04132500", "04214000",… ## $ date_prelevement <date> 2014-09-16, 2003-08-05, 2008-09-01, 2007-05-02… ## $ code_support <int> NA, 3, NA, NA, 3, NA, NA, 3, NA, 3, 3, 3, NA, N… ## $ libelle_station <chr> "MOZEE à CHANTONNAY", "MAYENNE à DAON", "MAYENN… ## $ date_creation <date> 1900-01-01, 1900-01-01, 1900-01-01, 1900-01-01… ## $ source <chr> "AELB", "AELB", "AELB", "AELB", "AELB", "AELB",… ## $ code_masse_eau <chr> "GR1950", "GR0460c", "GR0460c", "GR0121", "GR04… ## $ code_entite_hydro <chr> "N3036200", "M---0090", "M---0090", "J78-0300",… ## $ code_troncon_hydro <chr> "N3036200", "M3620090", "M3910090", "J7800300",… ## $ code_commune <chr> "85051", "53089", "49214", "44036", "53017", "5… ## $ date_formatee <chr> "16/09/2014", "05/08/2003", "01/09/2008", "02/0… 5.5.4 Manipuler des chaînes de caractères Le package {stringr} compile l’ensemble des fonctions de manipulation de chaînes de caractère utiles sur ce type de données. On peut diviser les manipulations de chaînes de caractères en 4 catégories : manipulations des caractères eux-mêmes, gestion des espaces, opérations liées à la langue, manipulations de “pattern”, notamment des expressions régulières. 5.5.4.1 Manipulations sur les caractères Obtenir la longueur d’une chaîne avec str_length() : library(stringr) str_length("abc") ## [1] 3 Extraire une chaîne de caractères avec str_sub() str_sub() prend 3 arguments : une chaîne de caractère, une position de début, une position de fin. Les positions peuvent être positives, et dans ce cas, on compte à partir de la gauche, ou négatives, et dans ce cas on compte à partir de la droite. a <- data.frame(x = c(" libeatg", "delivo y")) b <- mutate(a, pos3a4 = str_sub(string = x, start = 3, end = 4), pos3a2avtlafin = str_sub(string = x, start = 3, end = -2)) datatable(b) str_sub() peut être utilisé pour remplacer un caractère str_sub(a$x, start = 6, end = 9) <-"rer" a$x ## [1] " liberer" "delivrer" Si on souhaite réaliser ce genre d’opération dans le cadre d’un mutate, il faut utiliser une fonction dite “pipe-operator-friendly”, par exemple stri_sub_replace() du package {stringi} # install.packages("stringi") library(stringi) a <- data.frame(x = c(" libeatg", "delivo y")) b <- mutate(a, y=stri_sub_replace(str=x, from=6, to=9, value = "rer")) datatable(b) 5.5.4.2 Gestion des espaces La fonction str_pad() permet de compléter une chaîne de caractère pour qu’elle atteigne une taille fixe. Le cas typique d’usage est la gestion des codes communes Insee. code_insee <- 1001 str_pad(code_insee, 5, pad = "0") ## [1] "01001" On peut choisir de compléter à gauche, à droite, et on peut choisir le “pad”. Par défaut, celui-ci est l’espace. La fonction inverse de str_pad() est str_trim() qui permet de supprimer les espaces aux extrémités de notre chaîne de caractères. proust <- " Les paradoxes d'aujourd'hui sont les préjugés de demain. " str_trim(proust) ## [1] "Les paradoxes d'aujourd'hui sont les préjugés de demain." str_trim(proust, side = "left") ## [1] "Les paradoxes d'aujourd'hui sont les préjugés de demain. " Les expressions régulières permettent la détection de “patterns” sur des chaînes de caractères. Par exemple “^” sert à indiquer que la chaîne de caractère recherchée doit se trouver au début de la chaîne examinée. Au contraire, “$” sert à indiquer que la chaîne de caractère recherchée doit se trouver à la fin. a <- data.frame(txt = c("vélo", "train", "voilier", "bus", "avion", "tram", "trottinette")) b <- mutate(a, tr_au_debut = str_detect(string = txt, pattern = "^tr")) b ## txt tr_au_debut ## 1 vélo FALSE ## 2 train TRUE ## 3 voilier FALSE ## 4 bus FALSE ## 5 avion FALSE ## 6 tram TRUE ## 7 trottinette TRUE filter(b, tr_au_debut) ## txt tr_au_debut ## 1 train TRUE ## 2 tram TRUE ## 3 trottinette TRUE filter(a, str_detect(string = txt, pattern = "n$")) ## txt ## 1 train ## 2 avion 5.5.4.3 Opérations liées à la langue Ces différentes fonctions ne donneront pas le même résultat en fonction de la langue par défaut utilisée. La gestion des majuscules/minuscules : proust <- "Les paradoxes d'aujourd'hui sont LES préjugés de Demain." str_to_upper(proust) ## [1] "LES PARADOXES D'AUJOURD'HUI SONT LES PRÉJUGÉS DE DEMAIN." str_to_lower(proust) ## [1] "les paradoxes d'aujourd'hui sont les préjugés de demain." str_to_title(proust) ## [1] "Les Paradoxes D'aujourd'hui Sont Les Préjugés De Demain." La gestion de l’ordre, str_sort() et str_order() : a <- data.frame(x = c("y", "i", "k")) mutate(a, en_ordre = str_sort(x), selon_position = str_order(x)) ## x en_ordre selon_position ## 1 y i 2 ## 2 i k 3 ## 3 k y 1 Suppression des accents (base::iconv) : proust2 <- "Les paradoxes d'aujourd'hui sont les préjugés de demain ; et ça c'est embêtant" iconv(proust2, to = "ASCII//TRANSLIT") ## [1] "Les paradoxes d'aujourd'hui sont les prejuges de demain ; et ca c'est embetant" Avec humour, un petit aide-mémoire illustré, très visuel, est proposé par Lise Vaudor ici. 5.5.5 Manipuler des variables factorielles ( = qualitatives ou catégorielles) Les facteurs (ou factors, an anglais) sont un type de vecteur géré nativement par R qui permettent de gérer les variables qualitatives ou catégorielles. Les facteurs sont souvent mis en regard des données labellisées utilisées dans d’autres logiciels statistiques. Les facteurs possèdent un attribut appelé niveaux (levels, en anglais) qui contient l’ensemble des valeurs qui peuvent être prises par les éléments du vecteur. Les fonctions du module {forcats} permettent de modifier les modalités d’une variable factorielle, notamment : changer les modalités des facteurs et/ou leur ordre, regrouper des modalités. On va ici utiliser la fonction fct_infreq(), pour modifier le tri des stations en fonction de leur fréquence d’apparition dans la table “prelevement”. {forcats} permet beaucoup d’autres possibilités de tri : tri manuel des facteurs avec fct_relevel() ; en fonction de la valeur d’une autre variable avec fct_reorder(); en fonction de l’ordre d’apparition des modalités avec fct_inorder(). Consulter la documentation du package {forcats} pour voir toutes les possibilités très riches de ce module. En quoi ces fonctions sont utiles ? Elles permettent notamment : lorsqu’on fait des graphiques, d’afficher les occurences les plus importantes d’abord ; de lier l’ordre d’une variable en fonction d’une autre (par exemple les code Insee des communes en fonction des régions). Exemple : ordonner les modalités d’un facteur pour améliorer l’aspect d’un graphique library(ggplot2) library(forcats) data <- data.frame(num = c(1, 8, 4, 3, 6, 7, 5, 2, 11, 3), cat = c(letters[1:10])) ggplot(data, aes(x = cat, num)) + geom_bar(stat = "identity") + xlab(label = "Facteur") + ylab(label = "Valeur") ggplot(data, aes(x = fct_reorder(cat, -num), num)) + geom_bar (stat = "identity") + xlab(label = "Facteur ordonné") + ylab(label = "Valeur") 5.6 Agréger des données : summarise() La fonction summarise() permet d’agréger des données, en appliquant une fonction sur les variables pour construire une statistique sur les observations de la table. summarise() est une fonction dite de “résumé”. À l’inverse de mutate(), quand une fonction summarise est appelée, elle retourne une seule information. La moyenne, la variance, l’effectif… sont des informations qui condensent la variable étudiée en une seule information. La syntaxe de summarise est classique. Le résultat est un dataframe. summarise(exercice, mesure_moyenne = mean(resultat_analyse, na.rm = TRUE)) On peut calculer plusieurs statistiques sur une agrégation summarise(exercice, mesure_moyenne = mean(resultat_analyse, na.rm = TRUE), mesure_total = sum(resultat_analyse, na.rm = TRUE) ) 5.6.1 Quelques fonctions d’agrégations utiles compter : n() sommer : sum() compter des valeurs non manquantes sum(!is.na()) moyenne : mean(), moyenne pondérée : weighted.mean() écart-type : sd() médiane : median(), quantile : quantile(.,quantile) minimum : min(), maximum : max() position : first(), nth(., position), last() La plupart de ces fonctions d’agrégation sont paramétrables pour indiquer comment traiter les valeurs manquantes (NA) grâce à l’argument na.rm. Si on ne souhaite pas tenir compte des valeurs manquantes pour effectuer notre synthèse, il faut indiquer na.rm = TRUE pour évacuer les valeurs manquantes du calcul, sinon, le résultat apparaîtra comme lui même manquant, car il manque des observations pour pouvoir calculer correctement notre résultat. C’est la connaissance de votre source de données et du travail en court qui déterminera comment vous souhaitez que les valeurs manquantes soit traitées. 5.7 Agréger des données par dimension : group_by() La fonction summarise() est utile, mais la plupart du temps, nous avons besoin non pas d’agréger des données d’une table entière, mais de construire des agrégations sur des sous-ensembles : par année, département… La fonction group_by() va permettre d’éclater notre table en fonction de dimensions de celle-ci. Ainsi, si on veut construire des statistiques agrégées non sur l’ensemble de la table, mais pour chacune des modalités d’une ou de plusieurs variables de la table. Il faut deux étapes : utiliser préalablement la fonction group_by() pour définir la ou les variables sur lesquelles on souhaite agréger les données, utiliser summarise() sur la table en sortie de l’étape précédente. Découper un jeu de données pour réaliser des opérations sur chacun des sous-ensembles afin de les restituer ensuite de façon organisée est appelée stratégie du split – apply – combine schématiquement, c’est cette opération qui est réalisée par dplyr dès qu’un group_by() est introduit sur une table. Exemple pour calculer les statistiques précédentes par année : exercice <- mutate(exercice, annee = year(date_prelevement)) paran <- group_by(exercice, annee) summarise(paran, mesure_moyenne = mean(resultat_analyse, na.rm = TRUE), mesure_total = sum(resultat_analyse, na.rm = TRUE)) ## # A tibble: 26 × 3 ## annee mesure_moyenne mesure_total ## <dbl> <dbl> <dbl> ## 1 1991 0.0724 1.38 ## 2 1992 0.192 4.42 ## 3 1993 0.137 2.46 ## 4 1994 0.07 2.24 ## 5 1995 0.0687 2.06 ## 6 1996 0.0867 3.99 ## 7 1997 0.0520 2.50 ## 8 1998 0.145 22.8 ## 9 1999 0.0672 44.6 ## 10 2000 0.0586 36.9 ## # ℹ 16 more rows Pour reprendre des traitements “table entière”, il faut mettre fin au group_by() par un ungroup(). La fonction summarise() accepte désormais un argument .groups qui permet d’indiquer directement comment nous souhaitons voir ré-assemblé ou non notre jeu de données. paran <- group_by(exercice, annee, code_reseau) resultat <- summarise(paran, mesure_moyenne = mean(resultat_analyse, na.rm = TRUE), mesure_total = sum(resultat_analyse, na.rm = TRUE)) ## `summarise()` has grouped output by 'annee'. You can override using the ## `.groups` argument. Si on omet de lui déclarer comment traiter les groupes en sortie, summarise() nous informe des éventuels groupes résiduels, ici resultat est toujours groupé par annee. Pour remédier à ce message ou changer le comportement de summarise(), .groups peut prendre plusieurs valeurs : \"drop_last\" : va supprimer le dernier niveau de groupement de notre jeu de données. Dans notre exemple le groupe selon code_reseau va disparaître et celui lié à annee va rester. C’est le comportement par défaut. \"drop\" : supprime tous les niveaux de groupement \"keep\" : conserve tous les niveaux de groupement. \"rowwise\" : chaque ligne devient son propre groupe. resultat <- summarise(paran, mesure_moyenne = mean(resultat_analyse, na.rm = TRUE), mesure_total = sum(resultat_analyse, na.rm = TRUE), .groups = "drop") 5.8 Le pipe Le pipe est la fonction qui va vous permettre d’écrire votre code de façon plus lisible pour vous et les utilisateurs. Comment ? En se rapprochant de l’usage usuel en grammaire. verbe(sujet, complement) devient sujet %>% verbe(complement) Quand on enchaîne plusieurs verbes, l’avantage devient encore plus évident : verbe2(verbe1(sujet, complement1), complement2) devient sujet %>% verbe1(complement1) %>% verbe2(complement2) En reprenant l’exemple précédent, sans passer par les étapes intermédiaires, le code aurait cette tête : summarise ( group_by ( mutate ( exercice, annee = year(date_prelevement) ), annee ), mesure_moyenne = mean(resultat_analyse, na.rm = TRUE), mesure_total = sum(resultat_analyse, na.rm = TRUE) ) ## # A tibble: 26 × 3 ## annee mesure_moyenne mesure_total ## <dbl> <dbl> <dbl> ## 1 1991 0.0724 1.38 ## 2 1992 0.192 4.42 ## 3 1993 0.137 2.46 ## 4 1994 0.07 2.24 ## 5 1995 0.0687 2.06 ## 6 1996 0.0867 3.99 ## 7 1997 0.0520 2.50 ## 8 1998 0.145 22.8 ## 9 1999 0.0672 44.6 ## 10 2000 0.0586 36.9 ## # ℹ 16 more rows Avec l’utilisation du pipe (raccourci clavier CTrl + Maj + M), il devient : exercice %>% mutate(annee = year(date_prelevement)) %>% group_by(annee) %>% summarise(mesure_moyenne = mean(resultat_analyse, na.rm = TRUE), mesure_total = sum(resultat_analyse, na.rm = TRUE)) ## # A tibble: 26 × 3 ## annee mesure_moyenne mesure_total ## <dbl> <dbl> <dbl> ## 1 1991 0.0724 1.38 ## 2 1992 0.192 4.42 ## 3 1993 0.137 2.46 ## 4 1994 0.07 2.24 ## 5 1995 0.0687 2.06 ## 6 1996 0.0867 3.99 ## 7 1997 0.0520 2.50 ## 8 1998 0.145 22.8 ## 9 1999 0.0672 44.6 ## 10 2000 0.0586 36.9 ## # ℹ 16 more rows 5.9 La magie des opérations groupées L’opération group_by() que nous venons de voir est très utile pour les agrégations, mais elle peut aussi servir pour créer des variables ou filtrer une table, puisque group_by() permet de traiter notre table en entrée comme autant de tables séparées par les modalités des variables de regroupement. 5.9.1 Exercice 3 A partir des données “sitadel” chargées dans l’exercice 1, effectuer les opérations suivantes en utilisant l’opérateur %>% : effectuer les mêmes calculs que ceux réalisés sur la région 52, mais sur chacune des régions –> à stocker dans ‘sit_ind’ calculer les agrégations par année civile pour chacune des régions, puis leur taux d’évolution d’une année sur l’autre (exemple : (val2015-val2014)/val2014) –> à stocker dans ‘sit_annuel’ Résultat attendu pour sit_ind : ## # A tibble: 5,356 × 12 ## date REG log_AUT ip_AUT ig_AUT colres_AUT i_AUT i_AUT_cum12 ## <chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> ## 1 200001 01 440 194 12 234 206 NA ## 2 200001 02 372 189 14 169 203 NA ## 3 200001 03 172 25 3 144 28 NA ## 4 200001 04 473 325 84 64 409 NA ## 5 200001 11 3029 754 318 1957 1072 NA ## 6 200001 21 547 274 94 179 368 NA ## 7 200001 22 475 328 16 131 344 NA ## 8 200001 23 569 445 35 89 480 NA ## 9 200001 24 1057 714 88 255 802 NA ## 10 200001 25 708 410 206 92 616 NA ## # ℹ 5,346 more rows ## # ℹ 4 more variables: i_AUT_cum12_lag12 <dbl>, i_AUT_cum_evo <dbl>, ## # log_AUT_cum12 <dbl>, part_i_AU <dbl> Résultat attendu pour sit_annuel : ## # A tibble: 468 × 10 ## REG annee log_AUT ip_AUT ig_AUT colres_AUT evol_an_log_AUT evol_an_ip_AUT ## <chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> ## 1 01 2000 6625 2776 674 3175 NA NA ## 2 02 2000 3956 1805 270 1881 NA NA ## 3 03 2000 1501 363 363 775 NA NA ## 4 04 2000 9749 4580 1246 3923 NA NA ## 5 11 2000 44443 8843 4836 30764 NA NA ## 6 21 2000 5519 3164 890 1465 NA NA ## 7 22 2000 6363 3819 721 1823 NA NA ## 8 23 2000 8803 4712 1256 2835 NA NA ## 9 24 2000 13386 7770 1867 3749 NA NA ## 10 25 2000 8678 5288 1401 1989 NA NA ## # ℹ 458 more rows ## # ℹ 2 more variables: evol_an_ig_AUT <dbl>, evol_an_colres_AUT <dbl> 5.9.2 Exercice 4 Sur les données FormationPreparationDesDonnees.RData, table exercice : 1/ calculer le taux de quantification pour chaque molécule et chacune des années : chaque molécule est identifiée par son code_parametre, le taux de quantification est le nombre de fois qu’une molécule est retrouvée (càd si code_remarque = 1) sur le nombre de fois où elle a été cherchée (càd si code_remarque = 1, 2, 7 ou 10). Pour cela : créer la variable annee créer la variable de comptage des présences pour chaque analyse (1=présent, 0=absent) créer la variable de comptage des recherches pour chaque analyse (1=recherchée, 0=non recherchée) pour chaque combinaison annee x code_parametre, calculer le taux de quantification 2/ trouver pour chaque station, sur l’année 2016, le prélèvement pour lequel la concentration cumulée, toutes substances confondues, est la plus élevée (~ le prélèvement le plus pollué). Pour cela : filtrer les concentrations quantifiées (code_remarque=1) et l’année 2016 sommer les concentrations (resultat_analyse) par combinaison code_station x code_prelevement ne conserver que le prélèvement avec le concentration maximale Résultats attendus : Résultat attendu pour le taux de quantification par molécule et année : ## # A tibble: 6,538 × 3 ## annee code_parametre taux_quantif ## <dbl> <dbl> <dbl> ## 1 1991 1129 0 ## 2 1991 1130 0 ## 3 1991 1176 0 ## 4 1991 1199 0 ## 5 1991 1212 0 ## 6 1991 1259 0 ## 7 1991 1263 100 ## 8 1991 1267 0 ## 9 1992 1101 0 ## 10 1992 1107 100 ## # ℹ 6,528 more rows Résultat attendu pour prélèvement le plus pollué de chaque station en 2016 : ## # A tibble: 176 × 3 ## libelle_station code_prelevement concentration_cumulee ## <chr> <int> <dbl> ## 1 ANGLE GUIGNARD-RETENUE 43003 0.04 ## 2 ANXURE À SAINT-GERMAIN-D'ANXURE 42228 0.02 ## 3 APREMONT-RETENUE 42895 0.035 ## 4 ARAIZE à CHATELAIS 41451 0.006 ## 5 ARON à MOULAY 41359 0.008 ## 6 AUBANCE À LOUERRE 41571 0.08 ## 7 AUBANCE à MURS-ERIGNE 41542 0.317 ## 8 AUBANCE à SAINT-SATURNIN-SUR-LOIRE 41584 0.167 ## 9 AUTHION à LES PONTS-DE-CE 42532 0.27 ## 10 AUTISE À SAINT-HILAIRE-DES-LOGES 41998 0.048 ## # ℹ 166 more rows 5.10 Les armes non conventionnelles de la préparation des donnéees Nous venons de voir les principaux verbes de manipulation d’une table de dplyr. Ces verbes acquièrent encore plus de puissance quand ils sont appelés avec les fonctions across() et/ou where(). 5.10.1 Les select helpers Répéter des opérations de nettoyage ou de typage sur les différentes variables d’un jeu de données peut s’avérer fastidieux lorsque l’on a à écrire les opérations variable par variable. La fonction select() propose cinq manières différentes de désigner les variables à sélectionner. Nous avons vu la première et la plus intuitive, qui est de nommer les variables une à une. On peut également utiliser les : qui permettent de sélectionner une liste de variables consécutives. On peut également désigner les variables à sélectionner en fonction de leur position : select(exercice, code_analyse, code_laboratoire, code_prelevement, code_parametre, code_fraction_analysee, resultat_analyse, code_remarque) %>% names() ## [1] "code_analyse" "code_laboratoire" "code_prelevement" ## [4] "code_parametre" "code_fraction_analysee" "resultat_analyse" ## [7] "code_remarque" select(exercice, code_analyse:code_remarque) %>% names() ## [1] "code_analyse" "code_laboratoire" "code_prelevement" ## [4] "code_parametre" "code_fraction_analysee" "resultat_analyse" ## [7] "code_remarque" select(exercice, -c(code_analyse:code_remarque)) %>% names() ## [1] "limite_detection" "limite_quantification" "code_intervenant" ## [4] "code_reseau" "code_station" "date_prelevement" ## [7] "code_support" "libelle_station" "date_creation" ## [10] "source" "code_masse_eau" "code_entite_hydro" ## [13] "code_troncon_hydro" "code_commune" select(exercice, 1:7) %>% names() ## [1] "code_analyse" "code_laboratoire" "code_prelevement" ## [4] "code_parametre" "code_fraction_analysee" "resultat_analyse" ## [7] "code_remarque" select(exercice, -c(1:7)) %>% names() ## [1] "limite_detection" "limite_quantification" "code_intervenant" ## [4] "code_reseau" "code_station" "date_prelevement" ## [7] "code_support" "libelle_station" "date_creation" ## [10] "source" "code_masse_eau" "code_entite_hydro" ## [13] "code_troncon_hydro" "code_commune" Sélectionner les variables en fonction de leur position peut sembler séduisant, mais attention aux problèmes de reproductibilité que cela peut poser si le jeu de données en entrée bouge un peu entre deux millésimes. On peut également sélectionner des variables selon des conditions sur leur nom. Par exemple, on peut sélectionner les variables dont le nom commence par “date”, ou se termine par “station”, ou contient “prel” ou en fonction d’une expression régulière comme “m.n” (le nom contient un “m” suivi d’un caractère suivi d’un “n”. select(exercice, starts_with("date")) %>% names() ## [1] "date_prelevement" "date_creation" select(exercice, ends_with("station")) %>% names() ## [1] "code_station" "libelle_station" select(exercice, contains("prel")) %>% names() ## [1] "code_prelevement" "date_prelevement" select(exercice, matches("m.n")) %>% names() ## [1] "code_prelevement" "date_prelevement" "code_commune" On peut également sélectionner des variables selon des conditions sur leur type, avec la fonction where(). Par exemple, sélectionner toutes les variables numériques ou toutes les variables de type caractère. select(exercice, where(is.numeric)) %>% names() ## [1] "code_analyse" "code_laboratoire" "code_prelevement" ## [4] "code_parametre" "code_fraction_analysee" "resultat_analyse" ## [7] "code_remarque" "limite_detection" "limite_quantification" ## [10] "code_support" select(exercice, where(is.character)) %>% names() ## [1] "code_station" "date_prelevement" "libelle_station" ## [4] "date_creation" "source" "code_masse_eau" ## [7] "code_entite_hydro" "code_troncon_hydro" "code_commune" On peut enfin sélectionner des variables en combinant les moyens détaillés ci-avant et en recourant aux opérateurs booléens : ! (négation), & (et), | (ou). select(exercice, 1:7 & starts_with("code")) %>% names() ## [1] "code_analyse" "code_laboratoire" "code_prelevement" ## [4] "code_parametre" "code_fraction_analysee" "code_remarque" select(exercice, starts_with("date") & !where(is.Date)) %>% names() ## [1] "date_prelevement" "date_creation" 5.10.2 Utiliser les select helpers avec les autres verbes du tidyverse 5.10.2.1 rename() et rename_with() Lorsqu’on souhaite renommer les variable une à une, la fonction rename() fonctionne de la même manière que select() : mon_df_renomme <- rename(mon_dataframe, nouveau_nom1 = ancien_nom1, nouveau_nom2 = ancien_nom2) Si l’on souhaite recourir aux select helpers, il faut utiliser rename_with(), avec la syntaxe rename_with(.data= mon_df, .fn= ma_fonction_de_renommage, .cols= les_variables_a_renommer). Exemple avec la fonction toupper() qui passe les chaînes de caractères en majuscules. rename_with(station, toupper, starts_with("code")) %>% names() ## [1] "CODE_STATION" "libelle_station" "date_creation" ## [4] "source" "CODE_MASSE_EAU" "CODE_ENTITE_HYDRO" ## [7] "CODE_TRONCON_HYDRO" "CODE_COMMUNE" Si la fonction de renommage est plus complexe qu’un simple mot, il faut recourir au pronom .x et au ~ pour la définir. Exemple avec la fonction str_sub() de {stringr} vue précédemment : rename_with(exercice, ~ str_sub(.x, start = 6, end = str_length(.x)), starts_with("code")) %>% names() ## [1] "analyse" "laboratoire" "prelevement" ## [4] "parametre" "fraction_analysee" "resultat_analyse" ## [7] "remarque" "limite_detection" "limite_quantification" ## [10] "intervenant" "reseau" "station" ## [13] "date_prelevement" "support" "libelle_station" ## [16] "date_creation" "source" "masse_eau" ## [19] "entite_hydro" "troncon_hydro" "commune" 5.10.3 filter(), mutate(), group_by(), summarise(), arrange(), transmute()… Les autres verbes de {dplyr} ont besoin de la fonction across() pour fonctionner avec les select helpers. Comme pour rename_with(), les fonctions complexes sont à déclarer avec le ~ et le pronom .x. On peut en désigner plusieurs ou leur fournir un nom qui servira de suffixe aux noms des variables calculées, en passant la ou les fonctions dans une liste : .fn=list(suffixe1 = ma_fonction1, suffixe2 = ma_fonction2). La syntaxe générale devient : monverbe(.data, across(mesvariables, malistedefonctions), across(mesvariables2, malistedefonctions2)) filter(parametre, across(starts_with("date"), ~ .x > "2015-01-01")) %>% select(1:7) ## code_parametre nom_parametre statut_parametre ## 1 7782 Desméthyl-chlortoluron Validé ## 2 7801 Cyprosulfamide Validé ## 3 7783 Haloxyfop méthyl Validé ## 4 7748 cyflufénamide Validé ## date_creation_parametre date_maj_parametre auteur_parametre parametre_calcule ## 1 2015-03-10 2015-03-27 INOVALYS Nantes FALSE ## 2 2015-04-30 2015-06-10 AERM FALSE ## 3 2015-03-10 2015-03-27 INOVALYS FALSE ## 4 2015-02-13 2015-02-13 CARSO-LSEHL FALSE mutate(exercice, across(starts_with("code") & where(is.numeric), as.factor), across(starts_with("date"), as.Date)) %>% head() %>% datatable() summarise(parametre, across(starts_with("code"), n_distinct)) ## code_parametre ## 1 435 group_by(prelevement, across(code_intervenant:code_station)) %>% summarise(across(everything(), list(nb = n_distinct)), .groups = "drop") ## # A tibble: 766 × 6 ## code_intervenant code_reseau code_station code_prelevement_nb ## <fct> <fct> <chr> <int> ## 1 44 ARS 044000001 51 ## 2 44 ARS 044000044 7 ## 3 44 ARS 044000045 5 ## 4 44 ARS 044000046 4 ## 5 44 ARS 044000047 3 ## 6 44 ARS 044000048 4 ## 7 44 ARS 044000070 6 ## 8 44 ARS 044000071 5 ## 9 44 ARS 044000076 4 ## 10 44 ARS 044000077 5 ## # ℹ 756 more rows ## # ℹ 2 more variables: date_prelevement_nb <int>, code_support_nb <int> Exemple sur l’exercice sur les données sitadel. sitadel <- read_excel("extdata/ROES_201702.xls", "AUT_REG") %>% group_by(REG) %>% mutate(across(where(is.numeric), list(cumul12 = ~ roll_sumr(.x, n = 12))), across(ends_with("cumul12"), list(evo = ~ 100 * .x / lag (.x, 12) - 100, part = ~ 100 *.x / log_AUT_cumul12))) datatable(sitadel) "],["manipuler-plusieurs-tables.html", "Chapitre 6 Manipuler plusieurs tables 6.1 Concepts généraux 6.2 Principaux exemples de jointure 6.3 Paramétrage du suffixe pour des colonnes présentes dans les deux tables 6.4 Animations de Garrick Abenduie 6.5 Exercice 5", " Chapitre 6 Manipuler plusieurs tables 6.1 Concepts généraux Le package {dplyr} possède également plusieurs fonctions permettant de travailler sur deux tables. On va pouvoir regrouper ces fonctions en plusieurs catégories de manipulations : pour fusionner des informations de deux tables entre elles : jointures transformantes, pour sélectionner des observations d’une table en fonction de celles présentes dans une autre table : jointures filtrantes, pour traiter deux tables ayant les mêmes colonnes et sélectionner sur celles-ci des observations de l’une et l’autre : opérations ensemblistes, des manipulations visant à additionner deux tables ensembles : assemblages. 6.2 Principaux exemples de jointure Dans la capture ci-dessus, les opérations de jointure supposent que la colonne x1 est présente dans a et b. Voici quelques exemples détaillant les principaux cas rencontrés : # jointure avec des noms de colonnes différentes pour la clé # `colonne_c` est une colonne de data_a et `colonne_d` est une colonne de data_b left_join(data_a, data_b, by = c("colonne_c" = "colonne_d")) # jointure sur deux colonnes # `colonne_e` et `colonne_f` sont des colonnes de data_a et de data_b left_join(data_a, data_b, by = c("colonne_e", "colonne_f")) # jointure sur deux colonnes avec noms différents # `colonne_g`et `colonne_i` sont des colonnes de data_a, `colonne_h` et `colonne_j` sont des colonnes de data_b left_join(data_a, data_b, by = c("colonne_g" = "colonne_h", "colonne_i" = "colonne_j")) 6.3 Paramétrage du suffixe pour des colonnes présentes dans les deux tables Dans le cas où des colonnes (hors jointure) sont présentes dans data_a et data_b, ces colonnes seront suffixées par : .x pour les colonnes provenant de data_a .y pour les colonnes provenant de data_b Il est possible de modifier ces suffixes en passant le paramètre suffix = c(\"_a\", \"_b\") au moment de la jointure. left_join(data_a, data_b, by = c("colonne_c" = "colonne_d"), suffix = c("_a", "_b")) 6.4 Animations de Garrick Abenduie Les animations proviennent de : https://www.garrickadenbuie.com/project/tidyexplain/ 6.4.1 Inner join 6.4.2 Left join 6.4.3 Pivot longuer / Pivot wider 6.5 Exercice 5 Dans les données FormationPreparationDesDonnees.RData, chaque analyse est effectuée à partir d’un prélèvement, lui-même réalisé au niveau d’une station. Reconstituer le dataframe exercice qui rassemble les données contenues dans les tables analyse, prelevement et station grâce à des jointures. Il faut partir de la table analyse et faire des jointures calculer le nombre d’analyses réalisées sur des molécules (identifiables par leur code_parametre) et décrites dans le référentiel parametre ; produire une liste des code_parametre associés à des analyses mais absents du référentiel ; produire une table des analyses “orphelines”, c’est-à-dire qui ne correspondent à aucun prélèvement. Résultats attendus : Résultat attendu pour les jointures entre analayse, prelevement et station ## Rows: 153,497 ## Columns: 22 ## $ code_analyse <int> 5186581, 280131, 1576225, 799894, 472800, 27671… ## $ code_laboratoire <dbl> NA, 292, NA, NA, 292, NA, NA, NA, NA, NA, NA, N… ## $ code_prelevement <int> 37593, 7715, 15517, 9566, 8332, 26792, 35625, 1… ## $ code_parametre <dbl> 1216, 1668, 1185, 1217, 1907, 1945, 1673, 1234,… ## $ code_fraction_analysee <int> 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,… ## $ resultat_analyse <dbl> 0.007, 0.050, 0.040, 0.050, 0.260, 0.020, 0.010… ## $ code_remarque <int> 10, 2, 2, 2, 1, 10, 10, 10, 10, 10, 10, 10, 2, … ## $ limite_detection <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,… ## $ limite_quantification <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,… ## $ code_intervenant <fct> NA, 104, NA, NA, 104, NA, NA, 53, NA, 44, 49, 4… ## $ code_reseau <fct> OSUR, OSUR, FREDON, OSUR, OSUR, OSUR, OSUR, ARS… ## $ code_station <chr> "04153800", "04130000", "04132500", "04214000",… ## $ date_prelevement <chr> "2014-09-16", "2003-08-05", "2008-09-01", "2007… ## $ code_support <int> NA, 3, NA, NA, 3, NA, NA, 3, NA, 3, 3, 3, NA, N… ## $ libelle_station <chr> "MOZEE à CHANTONNAY", "MAYENNE à DAON", "MAYENN… ## $ date_creation <chr> "1900-01-01", "1900-01-01", "1900-01-01", "1900… ## $ source <chr> "AELB", "AELB", "AELB", "AELB", "AELB", "AELB",… ## $ code_masse_eau <chr> "GR1950", "GR0460c", "GR0460c", "GR0121", "GR04… ## $ code_entite_hydro <chr> "N3036200", "M---0090", "M---0090", "J78-0300",… ## $ code_troncon_hydro <chr> "N3036200", "M3620090", "M3910090", "J7800300",… ## $ code_commune <chr> "85051", "53089", "49214", "44036", "53017", "5… ## $ annee <dbl> 2014, 2003, 2008, 2007, 2005, 2006, 2013, 2009,… Résultat attendu pour le nombre d’analyses réalisées sur des molécules (code_parametre) présentes dans le référentiel parametre : ## [1] 194382 Résultat attendu pour la liste des code_parametre associés à des analyses mais absents du référentiel : ## [1] 1261 1206 1673 1234 1686 1757 1666 1149 1865 1888 1225 1830 ## [13] 1506 1136 1218 1199 1664 7097 1913 1680 5526 1235 1533 1266 ## [25] 1155 1877 1215 1209 1126 1208 1189 9052 1526 1256 1903 1905 ## [37] 1866 1895 1171 1130 2027 2046 1104 1233 1193 2057 1890 1173 ## [49] 1148 1150 1103 2737 2047 1490 1464 1101 1254 1698 1540 1870 ## [61] 2912 1287 1159 1142 1257 1213 1812 1700 1194 1432 2546 6260 ## [73] 1289 1697 5537 1694 2074 1699 1951 2751 6398 1806 1228 2678 ## [85] 1814 1832 2806 2015 1809 1682 1742 3159 2807 1214 1402 1670 ## [97] 5921 0 1210 1276 1153 2028 1094 1968 6483 1124 1119 1891 ## [109] 1127 1139 1954 1503 1523 1887 1147 1522 1743 1972 1966 1763 ## [121] 2012 2976 1259 1701 1102 1231 1940 1238 2024 5416 1860 5760 ## [133] 1501 1942 6824 1280 1502 2951 1112 1975 1943 1336 1711 1716 ## [145] 1930 1764 1655 1283 1615 1976 1953 7057 2010 1805 2950 2930 ## [157] 1546 2565 5488 1880 1774 1684 1525 1959 1616 1592 1587 2769 ## [169] 2545 2750 2069 5638 2664 1702 1720 1538 1636 2984 5581 2913 ## [181] 6261 6856 1091 1875 7500 1090 1649 1614 1548 7345 2872 2987 ## [193] 1250 12143 2021 1274 1629 1465 2609 3209 1642 2748 1643 2744 ## [205] 1969 1869 7342 1591 1251 1647 2749 1116 2986 2066 1469 1388 ## [217] 2081 1245 2889 5545 1628 1648 2919 1595 1613 1957 1590 1955 ## [229] 1089 2929 2536 1160 3283 1282 1387 1458 7522 1241 3160 2732 ## [241] 1275 1651 1382 1106 1115 12098 1588 1468 1612 2916 1624 1594 ## [253] 12099 1032 1627 2733 1243 2734 1921 1273 2915 6384 1272 1117 ## [265] 1278 1653 1731 1586 1396 2887 1286 2770 5499 1305 1471 1650 ## [277] 1625 1645 1593 2868 1486 1730 1161 7150 2590 2032 1626 1589 ## [289] 1249 1386 1242 2537 1244 1644 1497 1622 2568 1577 1641 Résultat attendu pour la table des analyses “orphelines”, c’est-à-dire ne correspondent à aucun prélèvement : ## Rows: 84,535 ## Columns: 9 ## $ code_analyse <int> 3854590, 1812211, 3124130, 4245401, 3684301, 38… ## $ code_laboratoire <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,… ## $ code_prelevement <int> 32031, 17208, 28512, 33302, 31986, 32146, 17640… ## $ code_parametre <dbl> 2025, 1261, 2045, 2978, 2018, 1190, 1206, 1911,… ## $ code_fraction_analysee <int> 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,… ## $ resultat_analyse <dbl> 2e-02, 5e-02, 1e-02, 1e+01, 1e-02, 2e-02, 2e-02… ## $ code_remarque <int> 10, 10, 10, 10, 133, 10, 10, 10, 10, 10, 10, 10… ## $ limite_detection <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,… ## $ limite_quantification <dbl> 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, … "],["structurer-ses-tables.html", "Chapitre 7 Structurer ses tables 7.1 Pourquoi se pencher sur la structuration des tables ? 7.2 Les deux fonctions clefs de {tidyr}", " Chapitre 7 Structurer ses tables 7.1 Pourquoi se pencher sur la structuration des tables ? Pour bien manipuler des données, leur structuration est fondamentale. Il faut bien savoir ce qu’est : une ligne de notre table, une colonne de notre table. Sur une table non agrégée (un répertoire, une table d’enquête…), la structuration naturelle est une ligne par observation (un individu, une entreprise…), une colonne par variable (âge, taille…) sur cette observation. Mais dès qu’on agrège une telle table pour construire des tables structurées par dimensions d’analyse et indicateurs, se pose toujours la question de savoir ce qu’on va considérer comme des dimensions et comme des indicateurs. Le standard tidy data définit 3 principes pour des données propres : chaque variable est une colonne, chaque observation est une ligne, les unités d’observations différentes sont stockées dans des tables différentes. Le respect de ces règles va nous amener parfois à devoir changer la définition des lignes et colonnes de nos tables en entrée. Ci-dessous un exemple simple : la population estimée par département et genre en 2019. Ce fichier est un extrait d’un tableur mis à disposition par l’Insee. estim_pop <- read_excel('extdata/estim-pop-dep-sexe-gca-2019.xls') estim_pop ## # A tibble: 104 × 20 ## dep lib_dep Ensemble_019ans Ensemble_2039ans Ensemble_4059ans ## <chr> <chr> <dbl> <dbl> <dbl> ## 1 01 Ain 167720 150949 179476 ## 2 02 Aisne 131435 115046 137405 ## 3 03 Allier 67628 61986 87232 ## 4 04 Alpes-de-Haute-Prove… 33883 30028 43039 ## 5 05 Hautes-Alpes 30518 28633 37887 ## 6 06 Alpes-Maritimes 228072 237427 282270 ## 7 07 Ardèche 71385 62186 88572 ## 8 08 Ardennes 61006 56583 71821 ## 9 09 Ariège 31143 28962 41017 ## 10 10 Aube 74510 69537 78475 ## # ℹ 94 more rows ## # ℹ 15 more variables: Ensemble_6074ans <dbl>, Ensemble_75ansetplus <dbl>, ## # Ensemble_Total <dbl>, Homme_019ans <dbl>, Homme_2039ans <dbl>, ## # Homme_4059ans <dbl>, Homme_6074ans <dbl>, Homme_75ansetplus <dbl>, ## # Homme_Total <dbl>, Femme_019ans <dbl>, Femme_2039ans <dbl>, ## # Femme_4059ans <dbl>, Femme_6074ans <dbl>, Femme_75ansetplus <dbl>, ## # Femme_Total <dbl> En quoi ce fichier n’est pas tidy ? On retrouve 4 variables dans notre fichier : le territoire, le genre, l’âge et la population, et nos colonnes ne correspondent pas à ces variables. Quel serait la version tidy de notre fichier ? ## # A tibble: 1,872 × 5 ## dep lib_dep genre age nombre_individus ## <chr> <chr> <chr> <chr> <dbl> ## 1 01 Ain Ensemble 019ans 167720 ## 2 01 Ain Ensemble 2039ans 150949 ## 3 01 Ain Ensemble 4059ans 179476 ## 4 01 Ain Ensemble 6074ans 102788 ## 5 01 Ain Ensemble 75ansetplus 52755 ## 6 01 Ain Ensemble Total 653688 ## 7 01 Ain Homme 019ans 86359 ## 8 01 Ain Homme 2039ans 75242 ## 9 01 Ain Homme 4059ans 89278 ## 10 01 Ain Homme 6074ans 49523 ## # ℹ 1,862 more rows Comment passer facilement d’un format non tidy à un format tidy ? C’est là qu’intervient le package {tidyr}. 7.2 Les deux fonctions clefs de {tidyr} pivot_longer() permet d’empiler plusieurs colonnes (correspondant à des variables quantitatives). Elles sont repérées par création d’une variable qualitative, à partir de leurs noms. Le résultat est une table au format long. pivot_wider() fait l’inverse. Cette fonction crée autant de colonnes qu’il y a de modalités d’une variable qualitative, en remplissant chacune par le contenu d’une variable numérique. Le résultat est une table au format large. Pour avoir un aperçu illustré de ces fonctions, voir cette animation Reprenons notre table Insee d’estimation de population. Comment faire pour passer cette table dans le format tidy ? Première étape, retrouvons notre colonne population. Pour cela, il nous faut passer notre table au format long, grâce à pivot_longer(). estim_pop_tidy <- estim_pop %>% pivot_longer(-c(dep, lib_dep), values_to = "nombre_individus", names_to = "genre_age") datatable(estim_pop_tidy) Si nous voulions retrouver le format large, nous pourrions utiliser pivot_wider() estim_pop_nontidy <- estim_pop_tidy %>% pivot_wider(names_from = genre_age, values_from = nombre_individus) datatable(estim_pop_nontidy) Nous n’avons pas encore retrouvé nos deux variables genre et age, mais une seule variable mélange les deux. Pour cela, nous pouvons utiliser separate() du package {tidyr}. estim_pop_tidy <- estim_pop_tidy %>% separate(genre_age, sep = "_", into = c("genre", "age")) datatable(estim_pop_tidy) Mais pivot_longer() permet d’aller encore plus loin en spécifiant sur nos colonnes un moyen de distinguer nos deux variables directement avec l’argument names_sep. estim_pop_tidy <- estim_pop %>% pivot_longer(-c(dep, lib_dep), names_sep = "_", names_to = c("genre", "age"), values_to = "nombre_individus") datatable(estim_pop_tidy) Et pivot_wider() permet également d’utiliser deux variables pour définir les modalités à convertir en colonnes. estim_pop_tidy %>% pivot_wider(names_from = c(genre, age), values_from = nombre_individus) %>% datatable() Vous retrouverez une introduction complète à {tidyr} dans un article très bien fait de la documentation du package (en anglais). {tidyr} permet également de transformer des données sous forme de listes en dataframe tidy très simplement. "],["nettoyer-des-données-territoriales-gérer-les-évolutions-du-cog-code-officiel-géographique.html", "Chapitre 8 Nettoyer des données territoriales : gérer les évolutions du COG (code officiel géographique) 8.1 Mettre à jour une table comportant une colonne de code commune 8.2 Mettre à jour le COG et agréger aux différentes échelles 8.3 Sélectionner les territoires de ma zone de travail 8.4 Pour en savoir plus : utiliser les fonds de carte mis à disposition dans COGiter", " Chapitre 8 Nettoyer des données territoriales : gérer les évolutions du COG (code officiel géographique) Lorsque qu’on démarre en analyse de données territoriales, on est parfois surpris de constater que ce qui nous semblent être immuable, comme les contours des régions, départements, communes, ne l’est pas ! Chaque année des communes fusionnent (voire se séparent !), les régions ont bougé avec beaucoup de bruit début 2016, on a même vu récemment une commune changer de département. Bref toute chaîne de traitement de données qui a vocation a être pérennisée doit prendre en compte cette variabilité des contours territoriaux. Le COG ou Code officiel géographique des territoires est administré par l’INSEE, qui publie chaque année la nouvelle liste des communes, départements, regions, et une table de passage annuelle entre anciennes et nouvelles communes. Comme souvent avec R, des utilisateurs soucieux de partager leurs astuces ont conçu des packages pour faciliter les traitement de mise à jour du COG, on peut citer {COGugaison} de Kim Antunez, qui est très précis (conversion d’un millésime à un autre, contrôle des années de conversion, retour en arrière possible) mais seulement adapté pour les tables de données France entière, et le package DREAL Pays de la Loire, initié par Maël Theulière {COGiter}, qui est plus simple (un seul sens : la mise à jour), ce package comprend par ailleurs des services d’agrégation à différentes échelles, de gestion des noms, des contours géo, mais ne gère pas très bien les scission de communes. La mise à jour du COG d’une source avec ces packages n’est possible que si cette dernière est disponible au moins à la maille communale sans secrétisation. Dans ce chapitre sont présentés les usages les plus fréquents de {COGiter}. 8.1 Mettre à jour une table comportant une colonne de code commune Dans nos données relatives aux pesticides, la table des stations comprend le code commune de rattachement de chaque station. {COGiter} permet de tenir à jour cette information d’une fonction : library(COGiter) stations_cog_ok <- passer_au_cog_a_jour(.data = station, code_commune = code_commune, aggrege = FALSE, garder_info_supra = TRUE) Le paramètre “aggrege” sert à indiquer si on souhaite obtenir en sortie une table avec une ligne par commune à jour, en sommant les valeurs numériques de la table. Le paramètre “garder_info_supra” sert à indiquer si on souhaite obtenir en sortie une table comportant en plus les territoires supra-communaux (EPCI, DEP, REG, …) de rattachement. stations_cog_ok %>% names() ## [1] "code_station" "libelle_station" "date_creation" ## [4] "source" "code_masse_eau" "code_entite_hydro" ## [7] "code_troncon_hydro" "DEPCOM" "NOM_DEPCOM" ## [10] "EPCI" "NOM_EPCI" "DEP" ## [13] "NOM_DEP" "REG" "NOM_REG" ## [16] "DEPARTEMENTS_DE_L_EPCI" "REGIONS_DE_L_EPCI" 8.2 Mettre à jour le COG et agréger aux différentes échelles Dans nos données de l’enquête tourisme, l’INSEE nous indique que les communes utilisées pour diffuser les résultats sont de celles 2019. Elles on donc bougé depuis. Imaginions, que nous voudrions avoir les résultats de cette enquête non pas par commune, mais par EPCI et département : la fonction cogifier() nous aide à faire tout ça en un tour de main. glimpse(enq_tourisme) ## Rows: 34,953 ## Columns: 55 ## $ CODGEO <chr> "01001", "01002", "01004", "01005", "01006", "01007", "01008… ## $ LIBGEO <chr> "L'Abergement-Clémenciat", "L'Abergement-de-Varey", "Ambérie… ## $ REG <chr> "84", "84", "84", "84", "84", "84", "84", "84", "84", "84", … ## $ DEP <chr> "01", "01", "01", "01", "01", "01", "01", "01", "01", "01", … ## $ HT19 <dbl> 0, 0, 1, 2, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, … ## $ HT019 <dbl> 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, … ## $ HT119 <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, … ## $ HT219 <dbl> 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, … ## $ HT319 <dbl> 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, … ## $ HT419 <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, … ## $ HT519 <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, … ## $ HTCH19 <dbl> 0, 0, 35, 17, 0, 0, 0, 0, 15, 0, 9, 0, 10, 0, 19, 0, 0, 43, … ## $ HTCH019 <dbl> 0, 0, 0, 8, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,… ## $ HTCH119 <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, … ## $ HTCH219 <dbl> 0, 0, 35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 43, 23,… ## $ HTCH319 <dbl> 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 19, 0, 0, 0, 0, 0,… ## $ HTCH419 <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, … ## $ HTCH519 <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, … ## $ CPG19 <dbl> 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, … ## $ CPG019 <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, … ## $ CPG119 <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, … ## $ CPG219 <dbl> 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, … ## $ CPG319 <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, … ## $ CPG419 <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, … ## $ CPG519 <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, … ## $ CPGE19 <dbl> 0, 0, 0, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 121, 56,… ## $ CPGE019 <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, … ## $ CPGE119 <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, … ## $ CPGE219 <dbl> 0, 0, 0, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 121, 0, … ## $ CPGE319 <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0,… ## $ CPGE419 <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, … ## $ CPGE519 <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, … ## $ CPGEL19 <dbl> 0, 0, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 0… ## $ CPGEL019 <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, … ## $ CPGEL119 <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, … ## $ CPGEL219 <dbl> 0, 0, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 0… ## $ CPGEL319 <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, … ## $ CPGEL419 <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, … ## $ CPGEL519 <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, … ## $ CPGEO19 <dbl> 0, 0, 0, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 101, 56,… ## $ CPGEO019 <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, … ## $ CPGEO119 <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, … ## $ CPGEO219 <dbl> 0, 0, 0, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 101, 0, … ## $ CPGEO319 <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0,… ## $ CPGEO419 <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, … ## $ CPGEO519 <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, … ## $ VV19 <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, … ## $ VVUH19 <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, … ## $ VVLIT19 <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, … ## $ RT19 <dbl> 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, … ## $ RTUH19 <dbl> 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,… ## $ RTLIT19 <dbl> 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,… ## $ AJCS19 <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, … ## $ AJCSUH19 <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, … ## $ AJCSLIT19 <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, … enq_tourisme_epci_dep <- enq_tourisme %>% # on enlève les colonnes textes à mettre à jour select(-LIBGEO, -REG, -DEP) %>% cogifier(code_commune = CODGEO, communes = FALSE, epci = TRUE, departements = TRUE, regions = FALSE, metro = TRUE, franceprovince = FALSE, metrodrom = FALSE, drom = TRUE, na.rm = FALSE) glimpse(enq_tourisme_epci_dep) ## Rows: 1,352 ## Columns: 54 ## $ TypeZone <fct> Epci, Epci, Epci, Epci, Epci, Epci, Epci, Epci, Epci, Epci, … ## $ Zone <fct> "CC Faucigny - Glières", "CC du Pays de Pontchâteau St-Gilda… ## $ CodeZone <fct> 200000172, 200000438, 200000545, 200000628, 200000800, 20000… ## $ HT19 <dbl> 6, 5, 3, 11, 8, 1, 6, 9, 5, 2, 76, 6, 6, 4, 2, 1, 15, 15, 20… ## $ HT019 <dbl> 2, 2, 0, 2, 4, 1, 3, 2, 0, 1, 14, 4, 4, 0, 1, 1, 7, 5, 5, 2,… ## $ HT119 <dbl> 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 3, 0, 0, 0, 0, 0, 1, 0, 0, 0, … ## $ HT219 <dbl> 4, 1, 2, 6, 2, 0, 2, 2, 1, 0, 14, 0, 1, 2, 1, 0, 1, 10, 3, 0… ## $ HT319 <dbl> 0, 1, 1, 2, 1, 0, 1, 4, 0, 1, 27, 2, 1, 2, 0, 0, 6, 0, 9, 0,… ## $ HT419 <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 15, 0, 0, 0, 0, 0, 0, 0, 3, 0,… ## $ HT519 <dbl> 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, … ## $ HTCH19 <dbl> 77, 92, 121, 330, 138, 8, 68, 219, 184, 24, 2414, 102, 89, 1… ## $ HTCH019 <dbl> 16, 29, 0, 60, 46, 8, 21, 17, 0, 6, 250, 50, 47, 0, 7, 10, 1… ## $ HTCH119 <dbl> 0, 0, 0, 61, 17, 0, 0, 0, 7, 0, 84, 0, 0, 0, 0, 0, 59, 0, 0,… ## $ HTCH219 <dbl> 61, 11, 98, 146, 60, 0, 28, 28, 15, 0, 417, 0, 14, 32, 6, 0,… ## $ HTCH319 <dbl> 0, 16, 23, 63, 15, 0, 19, 59, 0, 18, 994, 52, 28, 82, 0, 0, … ## $ HTCH419 <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 162, 0, 538, 0, 0, 0, 0, 0, 0, 0, 11… ## $ HTCH519 <dbl> 0, 36, 0, 0, 0, 0, 0, 115, 0, 0, 131, 0, 0, 0, 0, 0, 0, 0, 0… ## $ CPG19 <dbl> 2, 7, 1, 5, 1, 0, 6, 11, 3, 1, 9, 2, 10, 4, 2, 0, 2, 5, 0, 1… ## $ CPG019 <dbl> 1, 3, 0, 1, 0, 0, 3, 2, 1, 1, 2, 1, 2, 3, 0, 0, 0, 3, 0, 0, … ## $ CPG119 <dbl> 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, … ## $ CPG219 <dbl> 1, 1, 0, 0, 0, 0, 2, 2, 2, 0, 1, 1, 3, 0, 1, 0, 0, 0, 0, 0, … ## $ CPG319 <dbl> 0, 2, 0, 2, 1, 0, 0, 5, 0, 0, 5, 0, 5, 1, 1, 0, 2, 0, 0, 1, … ## $ CPG419 <dbl> 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, … ## $ CPG519 <dbl> 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, … ## $ CPGE19 <dbl> 103, 419, 220, 603, 166, 0, 264, 922, 132, 35, 746, 142, 657… ## $ CPGE019 <dbl> 34, 101, 0, 30, 0, 0, 77, 145, 40, 35, 71, 100, 37, 106, 0, … ## $ CPGE119 <dbl> 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 0, 0… ## $ CPGE219 <dbl> 69, 6, 0, 0, 0, 0, 87, 135, 92, 0, 54, 42, 79, 0, 17, 0, 0, … ## $ CPGE319 <dbl> 0, 142, 0, 222, 166, 0, 0, 478, 0, 0, 505, 0, 541, 65, 224, … ## $ CPGE419 <dbl> 0, 170, 220, 276, 0, 0, 100, 110, 0, 0, 116, 0, 0, 0, 0, 0, … ## $ CPGE519 <dbl> 0, 0, 0, 75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,… ## $ CPGEL19 <dbl> 2, 76, 114, 116, 1, 0, 3, 254, 23, 0, 7, 27, 108, 73, 63, 0,… ## $ CPGEL019 <dbl> 2, 32, 0, 30, 0, 0, 2, 30, 23, 0, 7, 27, 28, 33, 0, 0, 0, 40… ## $ CPGEL119 <dbl> 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,… ## $ CPGEL219 <dbl> 0, 0, 0, 0, 0, 0, 1, 12, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0… ## $ CPGEL319 <dbl> 0, 18, 0, 8, 1, 0, 0, 158, 0, 0, 0, 0, 58, 40, 63, 0, 32, 0,… ## $ CPGEL419 <dbl> 0, 26, 114, 23, 0, 0, 0, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0… ## $ CPGEL519 <dbl> 0, 0, 0, 55, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,… ## $ CPGEO19 <dbl> 101, 343, 106, 487, 165, 0, 261, 668, 109, 35, 739, 115, 549… ## $ CPGEO019 <dbl> 32, 69, 0, 0, 0, 0, 75, 115, 17, 35, 64, 73, 9, 73, 0, 0, 0,… ## $ CPGEO119 <dbl> 0, 0, 0, 0, 0, 0, 0, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 0, 0… ## $ CPGEO219 <dbl> 69, 6, 0, 0, 0, 0, 86, 123, 92, 0, 54, 42, 57, 0, 17, 0, 0, … ## $ CPGEO319 <dbl> 0, 124, 0, 214, 165, 0, 0, 320, 0, 0, 505, 0, 483, 25, 161, … ## $ CPGEO419 <dbl> 0, 144, 106, 253, 0, 0, 100, 71, 0, 0, 116, 0, 0, 0, 0, 0, 0… ## $ CPGEO519 <dbl> 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,… ## $ VV19 <dbl> 0, 1, 0, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, … ## $ VVUH19 <dbl> 0, 20, 0, 0, 205, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,… ## $ VVLIT19 <dbl> 0, 76, 0, 0, 686, 0, 146, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0… ## $ RT19 <dbl> 0, 0, 0, 0, 1, 0, 0, 6, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 4, 0, … ## $ RTUH19 <dbl> 0, 0, 0, 0, 746, 0, 0, 440, 0, 0, 70, 0, 0, 0, 0, 0, 0, 0, 3… ## $ RTLIT19 <dbl> 0, 0, 0, 0, 4056, 0, 0, 2233, 0, 0, 360, 0, 0, 0, 0, 0, 0, 0… ## $ AJCS19 <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, … ## $ AJCSUH19 <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23,… ## $ AJCSLIT19 <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65,… 8.3 Sélectionner les territoires de ma zone de travail Et si je ne souhaite que les territoires de ma région ou de mon département ? # Département du Nord enq_tourisme_epci_dep %>% filtrer_cog(dep = "59") ## # A tibble: 18 × 54 ## TypeZone Zone CodeZone HT19 HT019 HT119 HT219 HT319 HT419 HT519 HTCH19 ## <fct> <fct> <fct> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> ## 1 Epci CA du… 2000306… 2 0 1 0 1 0 0 61 ## 2 Epci CA Co… 2000409… 9 4 0 0 4 1 0 130 ## 3 Epci CC de… 2000409… 3 0 0 0 3 0 0 107 ## 4 Epci CC Pé… 2000419… 2 0 0 0 2 0 0 49 ## 5 Epci CA de… 2000421… 5 1 0 1 2 1 0 204 ## 6 Epci CC Co… 2000432… 2 1 0 0 1 0 0 35 ## 7 Epci CC du… 2000433… 2 2 0 0 0 0 0 29 ## 8 Epci CA Ma… 2000433… 10 2 0 2 6 0 0 420 ## 9 Epci CC du… 2000434… 4 2 0 0 2 0 0 65 ## 10 Epci CA Do… 2000446… 10 2 0 1 6 1 0 527 ## 11 Epci CA de… 2000685… 11 6 0 0 5 0 0 445 ## 12 Epci Métro… 2000932… 113 29 4 15 45 17 3 7407 ## 13 Epci CU de… 2459004… 32 18 2 7 4 1 0 1371 ## 14 Epci CC Fl… 2459007… 1 1 0 0 0 0 0 52 ## 15 Epci CC du… 2459010… 0 0 0 0 0 0 0 0 ## 16 Epci CC Co… 2459011… 0 0 0 0 0 0 0 0 ## 17 Epci CA Va… 2459011… 20 9 0 5 4 2 0 1123 ## 18 Départements Nord 59 226 77 7 31 85 23 3 12025 ## # ℹ 43 more variables: HTCH019 <dbl>, HTCH119 <dbl>, HTCH219 <dbl>, ## # HTCH319 <dbl>, HTCH419 <dbl>, HTCH519 <dbl>, CPG19 <dbl>, CPG019 <dbl>, ## # CPG119 <dbl>, CPG219 <dbl>, CPG319 <dbl>, CPG419 <dbl>, CPG519 <dbl>, ## # CPGE19 <dbl>, CPGE019 <dbl>, CPGE119 <dbl>, CPGE219 <dbl>, CPGE319 <dbl>, ## # CPGE419 <dbl>, CPGE519 <dbl>, CPGEL19 <dbl>, CPGEL019 <dbl>, ## # CPGEL119 <dbl>, CPGEL219 <dbl>, CPGEL319 <dbl>, CPGEL419 <dbl>, ## # CPGEL519 <dbl>, CPGEO19 <dbl>, CPGEO019 <dbl>, CPGEO119 <dbl>, … # Région Bretagne enq_tourisme_epci_dep %>% filtrer_cog(reg = "53", garder_supra = TRUE) %>% arrange(desc(TypeZone)) ## # A tibble: 1,352 × 54 ## TypeZone Zone CodeZone HT19 HT019 HT119 HT219 HT319 HT419 HT519 HTCH19 ## <fct> <fct> <fct> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> ## 1 France France mé… FRMETRO 17720 4690 405 4363 5957 1936 369 642779 ## 2 France Départeme… DROM 229 102 2 29 64 27 5 11440 ## 3 Epci CC Faucig… 2000001… 6 2 0 4 0 0 0 77 ## 4 Epci CC du Pay… 2000004… 5 2 0 1 1 0 1 92 ## 5 Epci CC des Po… 2000005… 3 0 0 2 1 0 0 121 ## 6 Epci CC Rhône … 2000006… 11 2 1 6 2 0 0 330 ## 7 Epci CC Coeur … 2000008… 8 4 1 2 1 0 0 138 ## 8 Epci CC de la … 2000009… 1 1 0 0 0 0 0 8 ## 9 Epci CC Sauldr… 2000009… 6 3 0 2 1 0 0 68 ## 10 Epci CC du Pay… 2000048… 9 2 0 2 4 0 1 219 ## # ℹ 1,342 more rows ## # ℹ 43 more variables: HTCH019 <dbl>, HTCH119 <dbl>, HTCH219 <dbl>, ## # HTCH319 <dbl>, HTCH419 <dbl>, HTCH519 <dbl>, CPG19 <dbl>, CPG019 <dbl>, ## # CPG119 <dbl>, CPG219 <dbl>, CPG319 <dbl>, CPG419 <dbl>, CPG519 <dbl>, ## # CPGE19 <dbl>, CPGE019 <dbl>, CPGE119 <dbl>, CPGE219 <dbl>, CPGE319 <dbl>, ## # CPGE419 <dbl>, CPGE519 <dbl>, CPGEL19 <dbl>, CPGEL019 <dbl>, ## # CPGEL119 <dbl>, CPGEL219 <dbl>, CPGEL319 <dbl>, CPGEL419 <dbl>, … 8.4 Pour en savoir plus : utiliser les fonds de carte mis à disposition dans COGiter COGiter contient des fonds de cartes des contours administratifs, conçus à partir des couches admin-express de l’IGN et dont la géométrie a été encore simplifiée pour répondre aux besoins de visualisation statistique. Voici un exemple d’usage très sommaire : departements_geo %>% inner_join(enq_tourisme_epci_dep, by = c("DEP" = "CodeZone")) %>% select(HT19) %>% plot() Obtenir la liste des fonds de cartes et des fonctionnalités géo : https://maeltheuliere.github.io/COGiter/articles/filtre_geo.html "],["exercice-6-les-données-majic.html", "Chapitre 9 Exercice 6 : les données majic", " Chapitre 9 Exercice 6 : les données majic Calculer à partir des tables fournies dans le fichier majic.RData issues des fichiers fonciers (cf. http://piece-jointe-carto.developpement-durable.gouv.fr/NAT004/DTerNP/html3/_ff_descriptif_tables_image.html#pnb10) un indicateur d’étalement urbain entre 2009 et 2014 à la commune et à l’EPCI sur la région Pays de la Loire (départements 44, 49, 53, 72 et 85), et catégoriser chaque territoire. Définitions : artificialisation = dcnt07 + dcnt09 + dcnt10 + dcnt11 + dcnt12 + dcnt13 indicateur_etalement_simple = évolution de l’artificialisation / évolution de la population indicateur_etalement_avance, indicateur catégoriel qui vaut : 1 si la population progresse ou reste stable alors que l’artificialisation recule ; 2a si la population et l’artificialisation progressent ou sont stables et l’étalement urbain est inférieur ou égal à 1 (ou pop stable) ; 2b si la population et l’artificialisation reculent et l’indicateur d’étalement urbain est supéreur à 1 ; 2c si la population recule et l’indicateur d’étalement est compris entre 0 et 1 (inclus) ; 3 si la population progresse, l’artificialisation progresse plus vite que la population, tout en restant inférieure ou égale à 4,9 m² ; 4 si la population progresse, l’artificialisation est supérieure à 4,9 m², elle progresse plus vite que la population mais au plus 2 fois plus vite ; 5 si la population progresse, l’artificialisation progresse plus de 2 fois plus vite que la population et est supérieure à 4,9 m² ; 6 si la population recule et l’indicateur d’étalement urbain est négatif. Résultats attendus : Résultat attendu : création de l’indicateur artificialisation pour les deux millésimes de majic (solution COGiter) ## Rows: 1,304 ## Columns: 4 ## $ TypeZone <fct> Communes, Communes, Communes, Communes, Communes, Communes,… ## $ Zone <fct> "Abbaretz", "Aigrefeuille-sur-Maine", "Ancenis-Saint-Géréon… ## $ CodeZone <fct> 44001, 44002, 44003, 44005, 44006, 44007, 44009, 44010, 440… ## $ artif_2009 <dbl> 3064748, 2408844, 6859785, 6101987, 2379588, 3042688, 50259… ## Rows: 1,304 ## Columns: 4 ## $ TypeZone <fct> Communes, Communes, Communes, Communes, Communes, Communes,… ## $ Zone <fct> "Abbaretz", "Aigrefeuille-sur-Maine", "Ancenis-Saint-Géréon… ## $ CodeZone <fct> 44001, 44002, 44003, 44005, 44006, 44007, 44009, 44010, 440… ## $ artif_2014 <dbl> 3160057, 2485622, 7103107, 6496868, 2419875, 3105298, 52452… Résultat attendu : création de les indicateurs pop_2009 et pop_2014 pour les deux millésimes de majic (solution COGiter) ## Rows: 1,304 ## Columns: 4 ## $ TypeZone <fct> Communes, Communes, Communes, Communes, Communes, Communes, C… ## $ Zone <fct> "Abbaretz", "Aigrefeuille-sur-Maine", "Ancenis-Saint-Géréon",… ## $ CodeZone <fct> 44001, 44002, 44003, 44005, 44006, 44007, 44009, 44010, 44012… ## $ pop_2009 <dbl> 1909, 3214, 10639, 5894, 1810, 2465, 8265, 3185, 2595, 2591, … ## Rows: 1,302 ## Columns: 4 ## $ TypeZone <fct> Communes, Communes, Communes, Communes, Communes, Communes, C… ## $ Zone <fct> "Abbaretz", "Aigrefeuille-sur-Maine", "Ancenis-Saint-Géréon",… ## $ CodeZone <fct> 44001, 44002, 44003, 44005, 44006, 44007, 44009, 44010, 44012… ## $ pop_2014 <dbl> 2042, 3714, 10783, 6680, 1830, 2601, 8747, 3086, 2769, 2927, … Résultat attendu : jointude implicite sur idcom et création de l’indicateur d'étalement urbain(solution COGiter) : ## Rows: 1,304 ## Columns: 11 ## $ TypeZone <fct> Communes, Communes, Communes, Communes, Co… ## $ Zone <fct> "Abbaretz", "Aigrefeuille-sur-Maine", "Anc… ## $ CodeZone <fct> 44001, 44002, 44003, 44005, 44006, 44007, … ## $ artif_2009 <dbl> 3064748, 2408844, 6859785, 6101987, 237958… ## $ artif_2014 <dbl> 3160057, 2485622, 7103107, 6496868, 241987… ## $ pop_2009 <dbl> 1909, 3214, 10639, 5894, 1810, 2465, 8265,… ## $ pop_2014 <dbl> 2042, 3714, 10783, 6680, 1830, 2601, 8747,… ## $ evoarti <dbl> 3.109847857, 3.187337993, 3.547079099, 6.4… ## $ evopop <dbl> 6.966998, 15.556938, 1.353511, 13.335596, … ## $ ies <dbl> 0.446368388, 0.204882086, 2.620651010, 0.4… ## $ indicateur_etalement_avance <chr> "2a", "2a", "3", "2a", "3", "2a", "2a", "6… Résultat attendu pour etalement_urbain_commune: ## Rows: 1,232 ## Columns: 11 ## $ TypeZone <fct> Communes, Communes, Communes, Communes, Co… ## $ Zone <fct> "Abbaretz", "Aigrefeuille-sur-Maine", "Anc… ## $ CodeZone <fct> 44001, 44002, 44003, 44005, 44006, 44007, … ## $ artif_2009 <dbl> 3064748, 2408844, 6859785, 6101987, 237958… ## $ artif_2014 <dbl> 3160057, 2485622, 7103107, 6496868, 241987… ## $ pop_2009 <dbl> 1909, 3214, 10639, 5894, 1810, 2465, 8265,… ## $ pop_2014 <dbl> 2042, 3714, 10783, 6680, 1830, 2601, 8747,… ## $ evoarti <dbl> 3.109847857, 3.187337993, 3.547079099, 6.4… ## $ evopop <dbl> 6.966998, 15.556938, 1.353511, 13.335596, … ## $ ies <dbl> 0.446368388, 0.204882086, 2.620651010, 0.4… ## $ indicateur_etalement_avance <chr> "2a", "2a", "3", "2a", "3", "2a", "2a", "6… Résultat attendu pour etalement_urbain_epci: ## Rows: 71 ## Columns: 11 ## $ TypeZone <fct> Epci, Epci, Epci, Epci, Epci, Epci, Epci, … ## $ Zone <fct> "CC du Pays de Pontchâteau St-Gildas-des-B… ## $ CodeZone <fct> 200000438, 200023778, 200033298, 200040475… ## $ artif_2009 <dbl> 27594293, 44299964, 25161639, 24880690, 16… ## $ artif_2014 <dbl> 28629232, 46277932, 26955382, 25836264, 18… ## $ pop_2009 <dbl> 31965, 45278, 27906, 18370, 17608, 29131, … ## $ pop_2014 <dbl> 35112, 48610, 28168, 19004, 17017, 29304, … ## $ evoarti <dbl> 3.750555, 4.464943, 7.128880, 3.840625, 7.… ## $ evopop <dbl> 9.8451431, 7.3589823, 0.9388662, 3.4512793… ## $ ies <dbl> 0.3809548, 0.6067337, 7.5930733, 1.1128120… ## $ indicateur_etalement_avance <chr> "2a", "2a", "5", "3", "6", "3", "5", "2a",… Résultat attendu pour le graphique (vu au M5) : "],["aller-plus-loin.html", "Chapitre 10 Aller plus loin", " Chapitre 10 Aller plus loin Quelques références : R for data science : http://r4ds.had.co.nz/transform.html {dplyr}, Introduction : https://dplyr.tidyverse.org/articles/dplyr.html {dplyr}, manipulation de deux tables : https://dplyr.tidyverse.org/articles/two-table.html {tidyr} : https://tidyr.tidyverse.org/ {tidyr}, fonctions pivot : https://tidyr.tidyverse.org/articles/pivot.html Aide mémoire de Rstudio sur {dplyr} et {tidyr} (assez ancien) : https://www.rstudio.com/wp-content/uploads/2016/01/data-wrangling-french.pdf Si vous préférez vous mettre à {data.table} https://s3.amazonaws.com/assets.datacamp.com/img/blog/data+table+cheat+sheet.pdf "],["404.html", "Page not found", " Page not found The page you requested cannot be found (perhaps it was moved or renamed). You may want to try searching to find the page's new location, or use the table of contents to find the page you are looking for. "]]
diff --git a/structurer-ses-tables.html b/structurer-ses-tables.html
index 86dce77..533b916 100644
--- a/structurer-ses-tables.html
+++ b/structurer-ses-tables.html
@@ -6,7 +6,7 @@
Chapitre 7 Structurer ses tables | Préparer ses données avec R et le Tidyverse
-
+
@@ -23,7 +23,7 @@
-
+
@@ -52,14 +52,15 @@
-
+
+
-
-
-
-
-
-
+
+
+
+
+
+
+
@@ -367,35 +372,35 @@ 7.2 Les deux fonctions clefs de <
pivot_longer(-c(dep, lib_dep), values_to = "nombre_individus", names_to = "genre_age")
datatable(estim_pop_tidy)
-
-
+
+
Si nous voulions retrouver le format large, nous pourrions utiliser pivot_wider()
<- estim_pop_tidy %>%
estim_pop_nontidy pivot_wider(names_from = genre_age, values_from = nombre_individus)
datatable(estim_pop_nontidy)
-
-
+
+
Nous n’avons pas encore retrouvé nos deux variables genre
et age
, mais une seule variable mélange les deux.
Pour cela, nous pouvons utiliser separate()
du package {tidyr}
.
<- estim_pop_tidy %>%
estim_pop_tidy separate(genre_age, sep = "_", into = c("genre", "age"))
datatable(estim_pop_tidy)
-
-
+
+
Mais pivot_longer()
permet d’aller encore plus loin en spécifiant sur nos colonnes un moyen de distinguer nos deux variables directement avec l’argument names_sep
.
<- estim_pop %>%
estim_pop_tidy pivot_longer(-c(dep, lib_dep), names_sep = "_", names_to = c("genre", "age"),
values_to = "nombre_individus")
datatable(estim_pop_tidy)
-
-
+
+
Et pivot_wider()
permet également d’utiliser deux variables pour définir les modalités à convertir en colonnes.
%>%
estim_pop_tidy pivot_wider(names_from = c(genre, age), values_from = nombre_individus) %>%
datatable()
-
-
+
+
Vous retrouverez une introduction complète à {tidyr}
dans un article très bien fait de la documentation du package (en anglais).
{tidyr}
permet également de transformer des données sous forme de listes en dataframe tidy très simplement.