R-Paket „Tidr“ und seine neuen Funktionen „pivot_longer“ und „pivot_wider“.

Package aufgeräumter im Kern einer der beliebtesten Bibliotheken der R-Sprache enthalten - ordentlichversum.
Der Hauptzweck des Pakets besteht darin, die Daten in eine genaue Form zu bringen.

Bereits auf Habré verfügbar Veröffentlichung ist diesem Paket gewidmet, stammt aber aus dem Jahr 2015. Und ich möchte Sie über die aktuellsten Änderungen informieren, die vor einigen Tagen von der Autorin Hedley Wickham angekündigt wurden.

R-Paket „Tidr“ und seine neuen Funktionen „pivot_longer“ und „pivot_wider“.

SJK: Werden Gather() und Spread() veraltet sein?

Hadley Wickham: Bis zu einem gewissen Grad. Wir werden die Verwendung dieser Funktionen nicht mehr empfehlen und Fehler darin beheben, sie werden jedoch weiterhin in ihrem aktuellen Zustand im Paket vorhanden sein.

Inhalt

Wenn Sie sich für Datenanalyse interessieren, könnten Sie an meiner interessiert sein Telegram mit и Youtube Kanäle. Der größte Teil des Inhalts ist der R-Sprache gewidmet.

TidyData-Konzept

Ziel aufgeräumter – helfen Ihnen, die Daten in eine sogenannte saubere Form zu bringen. Ordentliche Daten sind Daten, bei denen:

  • Jede Variable befindet sich in einer Spalte.
  • Jede Beobachtung ist eine Zeichenfolge.
  • Jeder Wert ist eine Zelle.

Es ist viel einfacher und bequemer, bei der Analyse mit Daten zu arbeiten, die in übersichtlichen Daten dargestellt werden.

Hauptfunktionen im Tidr-Paket enthalten

Tidyr enthält eine Reihe von Funktionen zum Transformieren von Tabellen:

  • fill() — fehlende Werte in einer Spalte mit vorherigen Werten füllen;
  • separate() – teilt ein Feld mithilfe eines Trennzeichens in mehrere auf;
  • unite() – führt die Operation aus, mehrere Felder zu einem zu kombinieren, die umgekehrte Aktion der Funktion separate();
  • pivot_longer() — eine Funktion, die Daten vom Breitformat in das Langformat konvertiert;
  • pivot_wider() – eine Funktion, die Daten vom Langformat ins Breitformat konvertiert. Die umgekehrte Operation der von der Funktion ausgeführten Operation pivot_longer().
  • gather()obsolet — eine Funktion, die Daten vom Breitformat in das Langformat konvertiert;
  • spread()obsolet – eine Funktion, die Daten vom Langformat ins Breitformat konvertiert. Die umgekehrte Operation der von der Funktion ausgeführten Operation gather().

Neues Konzept zur Konvertierung von Daten vom Breit- ins Langformat und umgekehrt

Bisher wurden für diese Art der Transformation Funktionen verwendet gather() и spread(). Im Laufe der Jahre, in denen diese Funktionen existierten, wurde deutlich, dass für die meisten Benutzer, einschließlich des Autors des Pakets, die Namen dieser Funktionen und ihre Argumente nicht ganz offensichtlich waren und Schwierigkeiten bereiteten, sie zu finden und zu verstehen, welche dieser Funktionen konvertiert werden ein Datumsrahmen vom Breit- zum Langformat und umgekehrt.

Diesbezüglich in aufgeräumter Es wurden zwei neue, wichtige Funktionen hinzugefügt, die Datumsrahmen transformieren sollen.

Neue Funktionen pivot_longer() и pivot_wider() wurden von einigen Funktionen des Pakets inspiriert cdata, erstellt von John Mount und Nina Zumel.

Installation der aktuellsten Version von Tidr 0.8.3.9000

Um die neue, aktuellste Version des Pakets zu installieren aufgeräumter 0.8.3.9000Wenn neue Funktionen verfügbar sind, verwenden Sie den folgenden Code.

devtools::install_github("tidyverse/tidyr")

Zum Zeitpunkt des Verfassens dieses Artikels sind diese Funktionen nur in der Dev-Version des Pakets auf GitHub verfügbar.

Übergang zu neuen Funktionen

Tatsächlich ist es nicht schwer, alte Skripte auf die Arbeit mit neuen Funktionen zu übertragen; zum besseren Verständnis werde ich ein Beispiel aus der Dokumentation alter Funktionen nehmen und zeigen, wie dieselben Operationen mit neuen ausgeführt werden pivot_*() funktionen.

Konvertieren Sie das Breitformat in das Langformat.

Beispielcode aus der Dokumentation der Gather-Funktion

# example
library(dplyr)
stocks <- data.frame(
  time = as.Date('2009-01-01') + 0:9,
  X = rnorm(10, 0, 1),
  Y = rnorm(10, 0, 2),
  Z = rnorm(10, 0, 4)
)

# old
stocks_gather <- stocks %>% gather(key   = stock, 
                                   value = price, 
                                   -time)

# new
stocks_long   <- stocks %>% pivot_longer(cols      = -time, 
                                       names_to  = "stock", 
                                       values_to = "price")

Konvertieren von Langformat in Breitformat.

Beispielcode aus der Spread-Funktionsdokumentation

# old
stocks_spread <- stocks_gather %>% spread(key = stock, 
                                          value = price) 

# new 
stock_wide    <- stocks_long %>% pivot_wider(names_from  = "stock",
                                            values_from = "price")

Weil in den obigen Beispielen für die Arbeit mit pivot_longer() и pivot_wider(), in der Originaltabelle Aktien In den Argumenten sind keine Spalten aufgeführt Namen_zu и Werte_zu Ihre Namen müssen in Anführungszeichen stehen.

Eine Tabelle, die Ihnen dabei hilft, am einfachsten herauszufinden, wie Sie mit einem neuen Konzept arbeiten können aufgeräumter.

R-Paket „Tidr“ und seine neuen Funktionen „pivot_longer“ und „pivot_wider“.

Anmerkung des Autors

Der gesamte Text unten ist adaptiv, ich würde sogar sagen, kostenlose Übersetzung Vignetten von der offiziellen Website der Tidyverse-Bibliothek.

Ein einfaches Beispiel für die Konvertierung von Daten vom Breit- ins Langformat

pivot_longer () – Verlängert Datensätze, indem die Anzahl der Spalten verringert und die Anzahl der Zeilen erhöht wird.

R-Paket „Tidr“ und seine neuen Funktionen „pivot_longer“ und „pivot_wider“.

Um die im Artikel vorgestellten Beispiele auszuführen, müssen Sie zunächst die erforderlichen Pakete verbinden:

library(tidyr)
library(dplyr)
library(readr)

Nehmen wir an, wir haben eine Tabelle mit den Ergebnissen einer Umfrage, bei der Menschen (unter anderem) nach ihrer Religion und ihrem Jahreseinkommen gefragt wurden:

#> # A tibble: 18 x 11
#>    religion `<$10k` `$10-20k` `$20-30k` `$30-40k` `$40-50k` `$50-75k`
#>    <chr>      <dbl>     <dbl>     <dbl>     <dbl>     <dbl>     <dbl>
#>  1 Agnostic      27        34        60        81        76       137
#>  2 Atheist       12        27        37        52        35        70
#>  3 Buddhist      27        21        30        34        33        58
#>  4 Catholic     418       617       732       670       638      1116
#>  5 Don’t k…      15        14        15        11        10        35
#>  6 Evangel…     575       869      1064       982       881      1486
#>  7 Hindu          1         9         7         9        11        34
#>  8 Histori…     228       244       236       238       197       223
#>  9 Jehovah…      20        27        24        24        21        30
#> 10 Jewish        19        19        25        25        30        95
#> # … with 8 more rows, and 4 more variables: `$75-100k` <dbl>,
#> #   `$100-150k` <dbl>, `>150k` <dbl>, `Don't know/refused` <dbl>

Diese Tabelle enthält die Religionsdaten der Befragten in Zeilen und die Einkommensniveaus sind über die Spaltennamen verteilt. Die Anzahl der Befragten aus jeder Kategorie wird in den Zellwerten am Schnittpunkt von Religion und Einkommensniveau gespeichert. Um die Tabelle in ein ordentliches, korrektes Format zu bringen, reicht es aus, sie zu verwenden pivot_longer():

pew %>% 
  pivot_longer(cols = -religion, names_to = "income", values_to = "count")

pew %>% 
  pivot_longer(cols = -religion, names_to = "income", values_to = "count")
#> # A tibble: 180 x 3
#>    religion income             count
#>    <chr>    <chr>              <dbl>
#>  1 Agnostic <$10k                 27
#>  2 Agnostic $10-20k               34
#>  3 Agnostic $20-30k               60
#>  4 Agnostic $30-40k               81
#>  5 Agnostic $40-50k               76
#>  6 Agnostic $50-75k              137
#>  7 Agnostic $75-100k             122
#>  8 Agnostic $100-150k            109
#>  9 Agnostic >150k                 84
#> 10 Agnostic Don't know/refused    96
#> # … with 170 more rows

Funktionsargumente pivot_longer()

  • Erstes Argument Spalten, beschreibt, welche Spalten zusammengeführt werden müssen. In diesem Fall alle Spalten außer Zeit.
  • Argument Namen_zu gibt den Namen der Variablen an, die aus den Namen der von uns verketteten Spalten erstellt wird.
  • Werte_zu gibt den Namen einer Variablen an, die aus den in den Werten der Zellen der zusammengeführten Spalten gespeicherten Daten erstellt wird.

Technische Daten

Dies ist eine neue Funktionalität des Pakets aufgeräumter, was bisher bei der Arbeit mit Legacy-Funktionen nicht verfügbar war.

Eine Spezifikation ist ein Datenrahmen, dessen jede Zeile einer Spalte im neuen Ausgabedatumsrahmen entspricht, sowie zwei spezielle Spalten, die beginnen mit:

  • . Name enthält den ursprünglichen Spaltennamen.
  • .wert enthält den Namen der Spalte, die die Zellwerte enthalten wird.

Die verbleibenden Spalten der Spezifikation spiegeln wider, wie die neue Spalte den Namen der komprimierten Spalten von anzeigt . Name.

Die Spezifikation beschreibt die in einem Spaltennamen gespeicherten Metadaten, mit einer Zeile für jede Spalte und einer Spalte für jede Variable, kombiniert mit dem Spaltennamen. Diese Definition mag im Moment verwirrend erscheinen, aber wenn man sich ein paar Beispiele ansieht, wird es viel klarer.

Der Sinn der Spezifikation besteht darin, dass Sie Metadaten für den zu konvertierenden Datenrahmen abrufen, ändern und definieren können.

Um beim Konvertieren einer Tabelle von einem Breitformat in ein Langformat mit Spezifikationen zu arbeiten, verwenden Sie die Funktion pivot_longer_spec().

Die Funktionsweise dieser Funktion besteht darin, dass sie einen beliebigen Datumsrahmen übernimmt und seine Metadaten auf die oben beschriebene Weise generiert.

Nehmen wir als Beispiel den Datensatz „who“, der mit dem Paket bereitgestellt wird aufgeräumter. Dieser Datensatz enthält Informationen der internationalen Gesundheitsorganisation zur Tuberkuloseinzidenz.

who
#> # A tibble: 7,240 x 60
#>    country iso2  iso3   year new_sp_m014 new_sp_m1524 new_sp_m2534
#>    <chr>   <chr> <chr> <int>       <int>        <int>        <int>
#>  1 Afghan… AF    AFG    1980          NA           NA           NA
#>  2 Afghan… AF    AFG    1981          NA           NA           NA
#>  3 Afghan… AF    AFG    1982          NA           NA           NA
#>  4 Afghan… AF    AFG    1983          NA           NA           NA
#>  5 Afghan… AF    AFG    1984          NA           NA           NA
#>  6 Afghan… AF    AFG    1985          NA           NA           NA
#>  7 Afghan… AF    AFG    1986          NA           NA           NA
#>  8 Afghan… AF    AFG    1987          NA           NA           NA
#>  9 Afghan… AF    AFG    1988          NA           NA           NA
#> 10 Afghan… AF    AFG    1989          NA           NA           NA
#> # … with 7,230 more rows, and 53 more variables

Lassen Sie uns seine Spezifikation erstellen.

spec <- who %>%
  pivot_longer_spec(new_sp_m014:newrel_f65, values_to = "count")

#> # A tibble: 56 x 3
#>    .name        .value name        
#>    <chr>        <chr>  <chr>       
#>  1 new_sp_m014  count  new_sp_m014 
#>  2 new_sp_m1524 count  new_sp_m1524
#>  3 new_sp_m2534 count  new_sp_m2534
#>  4 new_sp_m3544 count  new_sp_m3544
#>  5 new_sp_m4554 count  new_sp_m4554
#>  6 new_sp_m5564 count  new_sp_m5564
#>  7 new_sp_m65   count  new_sp_m65  
#>  8 new_sp_f014  count  new_sp_f014 
#>  9 new_sp_f1524 count  new_sp_f1524
#> 10 new_sp_f2534 count  new_sp_f2534
#> # … with 46 more rows

Felder Land, iso2, iso3 sind bereits Variablen. Unsere Aufgabe ist es, die Spalten mit umzudrehen new_sp_m014 auf newrel_f65.

Die Namen dieser Spalten speichern die folgenden Informationen:

  • Präfix new_ gibt an, dass die Spalte Daten zu neuen Tuberkulosefällen enthält, der aktuelle Datumsrahmen enthält jedoch nur Informationen zu neuen Krankheiten, sodass dieses Präfix im aktuellen Kontext keine Bedeutung hat.
  • sp/rel/sp/ep beschreibt eine Methode zur Diagnose einer Krankheit.
  • m/f Geschlecht des Patienten.
  • 014/1524/2535/3544/4554/65 Altersgruppe des Patienten.

Wir können diese Spalten mit der Funktion teilen extract()Verwendung regulärer Ausdrücke.

spec <- spec %>%
        extract(name, c("diagnosis", "gender", "age"), "new_?(.*)_(.)(.*)")

#> # A tibble: 56 x 5
#>    .name        .value diagnosis gender age  
#>    <chr>        <chr>  <chr>     <chr>  <chr>
#>  1 new_sp_m014  count  sp        m      014  
#>  2 new_sp_m1524 count  sp        m      1524 
#>  3 new_sp_m2534 count  sp        m      2534 
#>  4 new_sp_m3544 count  sp        m      3544 
#>  5 new_sp_m4554 count  sp        m      4554 
#>  6 new_sp_m5564 count  sp        m      5564 
#>  7 new_sp_m65   count  sp        m      65   
#>  8 new_sp_f014  count  sp        f      014  
#>  9 new_sp_f1524 count  sp        f      1524 
#> 10 new_sp_f2534 count  sp        f      2534 
#> # … with 46 more rows

Bitte beachten Sie die Spalte . Name sollte unverändert bleiben, da dies unser Index für die Spaltennamen des Originaldatensatzes ist.

Geschlecht und Alter (Spalten Geschlecht и Alter) haben feste und bekannte Werte, daher wird empfohlen, diese Spalten in Faktoren umzuwandeln:

spec <-  spec %>%
            mutate(
              gender = factor(gender, levels = c("f", "m")),
              age = factor(age, levels = unique(age), ordered = TRUE)
            ) 

Schließlich, um die von uns erstellte Spezifikation auf den ursprünglichen Datumsrahmen anzuwenden die Wir müssen ein Argument verwenden spec in Funktion pivot_longer().

who %>% pivot_longer(spec = spec)

#> # A tibble: 405,440 x 8
#>    country     iso2  iso3   year diagnosis gender age   count
#>    <chr>       <chr> <chr> <int> <chr>     <fct>  <ord> <int>
#>  1 Afghanistan AF    AFG    1980 sp        m      014      NA
#>  2 Afghanistan AF    AFG    1980 sp        m      1524     NA
#>  3 Afghanistan AF    AFG    1980 sp        m      2534     NA
#>  4 Afghanistan AF    AFG    1980 sp        m      3544     NA
#>  5 Afghanistan AF    AFG    1980 sp        m      4554     NA
#>  6 Afghanistan AF    AFG    1980 sp        m      5564     NA
#>  7 Afghanistan AF    AFG    1980 sp        m      65       NA
#>  8 Afghanistan AF    AFG    1980 sp        f      014      NA
#>  9 Afghanistan AF    AFG    1980 sp        f      1524     NA
#> 10 Afghanistan AF    AFG    1980 sp        f      2534     NA
#> # … with 405,430 more rows

Alles, was wir gerade gemacht haben, lässt sich schematisch wie folgt darstellen:

R-Paket „Tidr“ und seine neuen Funktionen „pivot_longer“ und „pivot_wider“.

Spezifikation mit mehreren Werten (.value)

Im obigen Beispiel die Spezifikationsspalte .wert nur einen Wert enthielt, ist dies in den meisten Fällen der Fall.

Gelegentlich kann es jedoch vorkommen, dass Sie Daten aus Spalten mit unterschiedlichen Datentypen in Werten sammeln müssen. Verwendung einer Legacy-Funktion spread() das wäre ziemlich schwierig zu machen.

Das folgende Beispiel stammt aus Vignetten zum Paket Datentabelle.

Lassen Sie uns einen Trainingsdatenrahmen erstellen.

family <- tibble::tribble(
  ~family,  ~dob_child1,  ~dob_child2, ~gender_child1, ~gender_child2,
       1L, "1998-11-26", "2000-01-29",             1L,             2L,
       2L, "1996-06-22",           NA,             2L,             NA,
       3L, "2002-07-11", "2004-04-05",             2L,             2L,
       4L, "2004-10-10", "2009-08-27",             1L,             1L,
       5L, "2000-12-05", "2005-02-28",             2L,             1L,
)
family <- family %>% mutate_at(vars(starts_with("dob")), parse_date)

#> # A tibble: 5 x 5
#>   family dob_child1 dob_child2 gender_child1 gender_child2
#>    <int> <date>     <date>             <int>         <int>
#> 1      1 1998-11-26 2000-01-29             1             2
#> 2      2 1996-06-22 NA                     2            NA
#> 3      3 2002-07-11 2004-04-05             2             2
#> 4      4 2004-10-10 2009-08-27             1             1
#> 5      5 2000-12-05 2005-02-28             2             1

Der erstellte Datumsrahmen enthält in jeder Zeile Daten zu Kindern einer Familie. Familien können ein oder zwei Kinder haben. Für jedes Kind werden Daten zum Geburtsdatum und Geschlecht bereitgestellt, und die Daten für jedes Kind befinden sich in separaten Spalten; unsere Aufgabe ist es, diese Daten für die Analyse in das richtige Format zu bringen.

Bitte beachten Sie, dass wir über zwei Variablen mit Informationen zu jedem Kind verfügen: sein Geschlecht und sein Geburtsdatum (Spalten mit dem Präfix Taufe enthalten Geburtsdatum, Spalten mit Präfix Geschlecht das Geschlecht des Kindes enthalten). Das erwartete Ergebnis ist, dass sie in separaten Spalten angezeigt werden. Wir können dies tun, indem wir eine Spezifikation generieren, in der die Spalte .value wird zwei verschiedene Bedeutungen haben.

spec <- family %>%
  pivot_longer_spec(-family) %>%
  separate(col = name, into = c(".value", "child"))%>%
  mutate(child = parse_number(child))

#> # A tibble: 4 x 3
#>   .name         .value child
#>   <chr>         <chr>  <dbl>
#> 1 dob_child1    dob        1
#> 2 dob_child2    dob        2
#> 3 gender_child1 gender     1
#> 4 gender_child2 gender     2

Schauen wir uns also Schritt für Schritt die vom obigen Code ausgeführten Aktionen an.

  • pivot_longer_spec(-family) – Erstellen Sie eine Spezifikation, die alle vorhandenen Spalten außer der Familienspalte komprimiert.
  • separate(col = name, into = c(".value", "child")) - Spalte teilen . Name, das die Namen der Quellfelder enthält, indem Sie den Unterstrich verwenden und die resultierenden Werte in die Spalten eingeben .wert и der.
  • mutate(child = parse_number(child)) — Transformieren Sie die Feldwerte der vom Text- zum numerischen Datentyp.

Jetzt können wir die resultierende Spezifikation auf den ursprünglichen Datenrahmen anwenden und die Tabelle in die gewünschte Form bringen.

family %>% 
    pivot_longer(spec = spec, na.rm = T)

#> # A tibble: 9 x 4
#>   family child dob        gender
#>    <int> <dbl> <date>      <int>
#> 1      1     1 1998-11-26      1
#> 2      1     2 2000-01-29      2
#> 3      2     1 1996-06-22      2
#> 4      3     1 2002-07-11      2
#> 5      3     2 2004-04-05      2
#> 6      4     1 2004-10-10      1
#> 7      4     2 2009-08-27      1
#> 8      5     1 2000-12-05      2
#> 9      5     2 2005-02-28      1

Wir verwenden Argumente na.rm = TRUE, da die aktuelle Form der Daten die Erstellung zusätzlicher Zeilen für nicht vorhandene Beobachtungen erzwingt. Weil Familie 2 hat nur ein Kind, na.rm = TRUE garantiert, dass Familie 2 eine Zeile in der Ausgabe hat.

Konvertieren von Datumsrahmen vom Lang- ins Breitformat

pivot_wider() - ist die umgekehrte Transformation, und umgekehrt erhöht sich die Anzahl der Spalten des Datumsrahmens, indem die Anzahl der Zeilen verringert wird.

R-Paket „Tidr“ und seine neuen Funktionen „pivot_longer“ und „pivot_wider“.

Diese Art der Transformation wird äußerst selten verwendet, um Daten in eine genaue Form zu bringen. Diese Technik kann jedoch zum Erstellen von Pivot-Tabellen für Präsentationen oder zur Integration mit einigen anderen Tools nützlich sein.

Eigentlich die Funktionen pivot_longer() и pivot_wider() sind symmetrisch und erzeugen zueinander entgegengesetzte Wirkungen, d. h.: df %>% pivot_longer(spec = spec) %>% pivot_wider(spec = spec) и df %>% pivot_wider(spec = spec) %>% pivot_longer(spec = spec) gibt den ursprünglichen df zurück.

Das einfachste Beispiel für die Konvertierung einer Tabelle in ein Breitformat

Um zu demonstrieren, wie die Funktion funktioniert pivot_wider() Wir werden den Datensatz verwenden Fisch_Begegnungen, das Informationen darüber speichert, wie verschiedene Stationen die Bewegung von Fischen entlang des Flusses aufzeichnen.

#> # A tibble: 114 x 3
#>    fish  station  seen
#>    <fct> <fct>   <int>
#>  1 4842  Release     1
#>  2 4842  I80_1       1
#>  3 4842  Lisbon      1
#>  4 4842  Rstr        1
#>  5 4842  Base_TD     1
#>  6 4842  BCE         1
#>  7 4842  BCW         1
#>  8 4842  BCE2        1
#>  9 4842  BCW2        1
#> 10 4842  MAE         1
#> # … with 104 more rows

In den meisten Fällen ist diese Tabelle informativer und benutzerfreundlicher, wenn Sie die Informationen für jede Station in einer separaten Spalte darstellen.

fish_encounters %>% pivot_wider(names_from = station, values_from = seen)

fish_encounters %>% pivot_wider(names_from = station, values_from = seen)
#> # A tibble: 19 x 12
#>    fish  Release I80_1 Lisbon  Rstr Base_TD   BCE   BCW  BCE2  BCW2   MAE
#>    <fct>   <int> <int>  <int> <int>   <int> <int> <int> <int> <int> <int>
#>  1 4842        1     1      1     1       1     1     1     1     1     1
#>  2 4843        1     1      1     1       1     1     1     1     1     1
#>  3 4844        1     1      1     1       1     1     1     1     1     1
#>  4 4845        1     1      1     1       1    NA    NA    NA    NA    NA
#>  5 4847        1     1      1    NA      NA    NA    NA    NA    NA    NA
#>  6 4848        1     1      1     1      NA    NA    NA    NA    NA    NA
#>  7 4849        1     1     NA    NA      NA    NA    NA    NA    NA    NA
#>  8 4850        1     1     NA     1       1     1     1    NA    NA    NA
#>  9 4851        1     1     NA    NA      NA    NA    NA    NA    NA    NA
#> 10 4854        1     1     NA    NA      NA    NA    NA    NA    NA    NA
#> # … with 9 more rows, and 1 more variable: MAW <int>

Dieser Datensatz erfasst nur Informationen, wenn Fische von der Station erkannt wurden, d. h. Wenn ein Fisch von einer Station nicht erfasst wurde, sind diese Daten nicht in der Tabelle enthalten. Dies bedeutet, dass die Ausgabe mit NA gefüllt wird.

In diesem Fall wissen wir jedoch, dass das Fehlen einer Aufzeichnung bedeutet, dass der Fisch nicht gesehen wurde, sodass wir das Argument verwenden können Werte_Füllung in Funktion pivot_wider() und füllen Sie diese fehlenden Werte mit Nullen:

fish_encounters %>% pivot_wider(
  names_from = station, 
  values_from = seen,
  values_fill = list(seen = 0)
)

#> # A tibble: 19 x 12
#>    fish  Release I80_1 Lisbon  Rstr Base_TD   BCE   BCW  BCE2  BCW2   MAE
#>    <fct>   <int> <int>  <int> <int>   <int> <int> <int> <int> <int> <int>
#>  1 4842        1     1      1     1       1     1     1     1     1     1
#>  2 4843        1     1      1     1       1     1     1     1     1     1
#>  3 4844        1     1      1     1       1     1     1     1     1     1
#>  4 4845        1     1      1     1       1     0     0     0     0     0
#>  5 4847        1     1      1     0       0     0     0     0     0     0
#>  6 4848        1     1      1     1       0     0     0     0     0     0
#>  7 4849        1     1      0     0       0     0     0     0     0     0
#>  8 4850        1     1      0     1       1     1     1     0     0     0
#>  9 4851        1     1      0     0       0     0     0     0     0     0
#> 10 4854        1     1      0     0       0     0     0     0     0     0
#> # … with 9 more rows, and 1 more variable: MAW <int>

Generieren eines Spaltennamens aus mehreren Quellvariablen

Stellen Sie sich vor, wir haben eine Tabelle mit einer Kombination aus Produkt, Land und Jahr. Um einen Testdatumsrahmen zu generieren, können Sie den folgenden Code ausführen:

df <- expand_grid(
  product = c("A", "B"), 
  country = c("AI", "EI"), 
  year = 2000:2014
) %>%
  filter((product == "A" & country == "AI") | product == "B") %>% 
  mutate(value = rnorm(nrow(.)))

#> # A tibble: 45 x 4
#>    product country  year    value
#>    <chr>   <chr>   <int>    <dbl>
#>  1 A       AI       2000 -2.05   
#>  2 A       AI       2001 -0.676  
#>  3 A       AI       2002  1.60   
#>  4 A       AI       2003 -0.353  
#>  5 A       AI       2004 -0.00530
#>  6 A       AI       2005  0.442  
#>  7 A       AI       2006 -0.610  
#>  8 A       AI       2007 -2.77   
#>  9 A       AI       2008  0.899  
#> 10 A       AI       2009 -0.106  
#> # … with 35 more rows

Unsere Aufgabe besteht darin, den Datenrahmen so zu erweitern, dass eine Spalte Daten für jede Kombination aus Produkt und Land enthält. Übergeben Sie dazu einfach das Argument Namen_von ein Vektor, der die Namen der zusammenzuführenden Felder enthält.

df %>% pivot_wider(names_from = c(product, country),
                 values_from = "value")

#> # A tibble: 15 x 4
#>     year     A_AI    B_AI    B_EI
#>    <int>    <dbl>   <dbl>   <dbl>
#>  1  2000 -2.05     0.607   1.20  
#>  2  2001 -0.676    1.65   -0.114 
#>  3  2002  1.60    -0.0245  0.501 
#>  4  2003 -0.353    1.30   -0.459 
#>  5  2004 -0.00530  0.921  -0.0589
#>  6  2005  0.442   -1.55    0.594 
#>  7  2006 -0.610    0.380  -1.28  
#>  8  2007 -2.77     0.830   0.637 
#>  9  2008  0.899    0.0175 -1.30  
#> 10  2009 -0.106   -0.195   1.03  
#> # … with 5 more rows

Sie können Spezifikationen auch auf eine Funktion anwenden pivot_wider(). Aber wenn es eingereicht wird pivot_wider() Die Spezifikation führt die umgekehrte Konvertierung durch pivot_longer(): Die in angegebenen Spalten . Name, unter Verwendung von Werten aus .wert und andere Spalten.

Für diesen Datensatz können Sie eine benutzerdefinierte Spezifikation generieren, wenn Sie möchten, dass jede mögliche Kombination aus Land und Produkt eine eigene Spalte hat, nicht nur die in den Daten vorhandenen:

spec <- df %>% 
  expand(product, country, .value = "value") %>% 
  unite(".name", product, country, remove = FALSE)

#> # A tibble: 4 x 4
#>   .name product country .value
#>   <chr> <chr>   <chr>   <chr> 
#> 1 A_AI  A       AI      value 
#> 2 A_EI  A       EI      value 
#> 3 B_AI  B       AI      value 
#> 4 B_EI  B       EI      value

df %>% pivot_wider(spec = spec) %>% head()

#> # A tibble: 6 x 5
#>    year     A_AI  A_EI    B_AI    B_EI
#>   <int>    <dbl> <dbl>   <dbl>   <dbl>
#> 1  2000 -2.05       NA  0.607   1.20  
#> 2  2001 -0.676      NA  1.65   -0.114 
#> 3  2002  1.60       NA -0.0245  0.501 
#> 4  2003 -0.353      NA  1.30   -0.459 
#> 5  2004 -0.00530    NA  0.921  -0.0589
#> 6  2005  0.442      NA -1.55    0.594

Mehrere fortgeschrittene Beispiele für die Arbeit mit dem neuen Tidr-Konzept

Bereinigen von Daten am Beispiel des US Census Income and Rent-Datensatzes.

Datensatz us_rent_income Enthält Informationen zum Durchschnittseinkommen und zur Miete für jeden US-Bundesstaat für 2017 (Datensatz im Paket verfügbar). ordentliche Volkszählung).

us_rent_income
#> # A tibble: 104 x 5
#>    GEOID NAME       variable estimate   moe
#>    <chr> <chr>      <chr>       <dbl> <dbl>
#>  1 01    Alabama    income      24476   136
#>  2 01    Alabama    rent          747     3
#>  3 02    Alaska     income      32940   508
#>  4 02    Alaska     rent         1200    13
#>  5 04    Arizona    income      27517   148
#>  6 04    Arizona    rent          972     4
#>  7 05    Arkansas   income      23789   165
#>  8 05    Arkansas   rent          709     5
#>  9 06    California income      29454   109
#> 10 06    California rent         1358     3
#> # … with 94 more rows

In der Form, in der die Daten im Datensatz gespeichert sind us_rent_income Die Arbeit mit ihnen ist äußerst umständlich, daher möchten wir einen Datensatz mit Spalten erstellen: sauber, rent_moe, wie die, Einkommen_moe. Es gibt viele Möglichkeiten, diese Spezifikation zu erstellen, aber der Hauptpunkt ist, dass wir jede Kombination von Variablenwerten und generieren müssen Schätzung/moeund generieren Sie dann den Spaltennamen.

  spec <- us_rent_income %>% 
    expand(variable, .value = c("estimate", "moe")) %>% 
    mutate(
      .name = paste0(variable, ifelse(.value == "moe", "_moe", ""))
    )

#> # A tibble: 4 x 3
#>   variable .value   .name     
#>   <chr>    <chr>    <chr>     
#> 1 income   estimate income    
#> 2 income   moe      income_moe
#> 3 rent     estimate rent      
#> 4 rent     moe      rent_moe

Bereitstellung dieser Spezifikation pivot_wider() gibt uns das Ergebnis, das wir suchen:

us_rent_income %>% pivot_wider(spec = spec)

#> # A tibble: 52 x 6
#>    GEOID NAME                 income income_moe  rent rent_moe
#>    <chr> <chr>                 <dbl>      <dbl> <dbl>    <dbl>
#>  1 01    Alabama               24476        136   747        3
#>  2 02    Alaska                32940        508  1200       13
#>  3 04    Arizona               27517        148   972        4
#>  4 05    Arkansas              23789        165   709        5
#>  5 06    California            29454        109  1358        3
#>  6 08    Colorado              32401        109  1125        5
#>  7 09    Connecticut           35326        195  1123        5
#>  8 10    Delaware              31560        247  1076       10
#>  9 11    District of Columbia  43198        681  1424       17
#> 10 12    Florida               25952         70  1077        3
#> # … with 42 more rows

Weltbank

Manchmal sind mehrere Schritte erforderlich, um einen Datensatz in die gewünschte Form zu bringen.
Datensatz world_bank_pop enthält Daten der Weltbank zur Bevölkerung jedes Landes zwischen 2000 und 2018.

#> # A tibble: 1,056 x 20
#>    country indicator `2000` `2001` `2002` `2003`  `2004`  `2005`   `2006`
#>    <chr>   <chr>      <dbl>  <dbl>  <dbl>  <dbl>   <dbl>   <dbl>    <dbl>
#>  1 ABW     SP.URB.T… 4.24e4 4.30e4 4.37e4 4.42e4 4.47e+4 4.49e+4  4.49e+4
#>  2 ABW     SP.URB.G… 1.18e0 1.41e0 1.43e0 1.31e0 9.51e-1 4.91e-1 -1.78e-2
#>  3 ABW     SP.POP.T… 9.09e4 9.29e4 9.50e4 9.70e4 9.87e+4 1.00e+5  1.01e+5
#>  4 ABW     SP.POP.G… 2.06e0 2.23e0 2.23e0 2.11e0 1.76e+0 1.30e+0  7.98e-1
#>  5 AFG     SP.URB.T… 4.44e6 4.65e6 4.89e6 5.16e6 5.43e+6 5.69e+6  5.93e+6
#>  6 AFG     SP.URB.G… 3.91e0 4.66e0 5.13e0 5.23e0 5.12e+0 4.77e+0  4.12e+0
#>  7 AFG     SP.POP.T… 2.01e7 2.10e7 2.20e7 2.31e7 2.41e+7 2.51e+7  2.59e+7
#>  8 AFG     SP.POP.G… 3.49e0 4.25e0 4.72e0 4.82e0 4.47e+0 3.87e+0  3.23e+0
#>  9 AGO     SP.URB.T… 8.23e6 8.71e6 9.22e6 9.77e6 1.03e+7 1.09e+7  1.15e+7
#> 10 AGO     SP.URB.G… 5.44e0 5.59e0 5.70e0 5.76e0 5.75e+0 5.69e+0  4.92e+0
#> # … with 1,046 more rows, and 11 more variables: `2007` <dbl>,
#> #   `2008` <dbl>, `2009` <dbl>, `2010` <dbl>, `2011` <dbl>, `2012` <dbl>,
#> #   `2013` <dbl>, `2014` <dbl>, `2015` <dbl>, `2016` <dbl>, `2017` <dbl>

Unser Ziel ist es, einen übersichtlichen Datensatz mit jeder Variablen in einer eigenen Spalte zu erstellen. Es ist unklar, welche Schritte genau erforderlich sind, aber wir beginnen mit dem offensichtlichsten Problem: Das Jahr ist auf mehrere Spalten verteilt.

Um dies zu beheben, müssen Sie die Funktion verwenden pivot_longer().

pop2 <- world_bank_pop %>% 
  pivot_longer(`2000`:`2017`, names_to = "year")

#> # A tibble: 19,008 x 4
#>    country indicator   year  value
#>    <chr>   <chr>       <chr> <dbl>
#>  1 ABW     SP.URB.TOTL 2000  42444
#>  2 ABW     SP.URB.TOTL 2001  43048
#>  3 ABW     SP.URB.TOTL 2002  43670
#>  4 ABW     SP.URB.TOTL 2003  44246
#>  5 ABW     SP.URB.TOTL 2004  44669
#>  6 ABW     SP.URB.TOTL 2005  44889
#>  7 ABW     SP.URB.TOTL 2006  44881
#>  8 ABW     SP.URB.TOTL 2007  44686
#>  9 ABW     SP.URB.TOTL 2008  44375
#> 10 ABW     SP.URB.TOTL 2009  44052
#> # … with 18,998 more rows

Der nächste Schritt besteht darin, die Indikatorvariable zu betrachten.
pop2 %>% count(indicator)

#> # A tibble: 4 x 2
#>   indicator       n
#>   <chr>       <int>
#> 1 SP.POP.GROW  4752
#> 2 SP.POP.TOTL  4752
#> 3 SP.URB.GROW  4752
#> 4 SP.URB.TOTL  4752

Dabei ist SP.POP.GROW das Bevölkerungswachstum, SP.POP.TOTL die Gesamtbevölkerung und SP.URB. * das Gleiche, aber nur für städtische Gebiete. Teilen wir diese Werte in zwei Variablen auf: Fläche – Fläche (gesamt oder städtisch) und eine Variable, die tatsächliche Daten (Bevölkerung oder Wachstum) enthält:

pop3 <- pop2 %>% 
  separate(indicator, c(NA, "area", "variable"))

#> # A tibble: 19,008 x 5
#>    country area  variable year  value
#>    <chr>   <chr> <chr>    <chr> <dbl>
#>  1 ABW     URB   TOTL     2000  42444
#>  2 ABW     URB   TOTL     2001  43048
#>  3 ABW     URB   TOTL     2002  43670
#>  4 ABW     URB   TOTL     2003  44246
#>  5 ABW     URB   TOTL     2004  44669
#>  6 ABW     URB   TOTL     2005  44889
#>  7 ABW     URB   TOTL     2006  44881
#>  8 ABW     URB   TOTL     2007  44686
#>  9 ABW     URB   TOTL     2008  44375
#> 10 ABW     URB   TOTL     2009  44052
#> # … with 18,998 more rows

Jetzt müssen wir die Variable nur noch in zwei Spalten aufteilen:

pop3 %>% 
  pivot_wider(names_from = variable, values_from = value)

#> # A tibble: 9,504 x 5
#>    country area  year   TOTL    GROW
#>    <chr>   <chr> <chr> <dbl>   <dbl>
#>  1 ABW     URB   2000  42444  1.18  
#>  2 ABW     URB   2001  43048  1.41  
#>  3 ABW     URB   2002  43670  1.43  
#>  4 ABW     URB   2003  44246  1.31  
#>  5 ABW     URB   2004  44669  0.951 
#>  6 ABW     URB   2005  44889  0.491 
#>  7 ABW     URB   2006  44881 -0.0178
#>  8 ABW     URB   2007  44686 -0.435 
#>  9 ABW     URB   2008  44375 -0.698 
#> 10 ABW     URB   2009  44052 -0.731 
#> # … with 9,494 more rows

Kontaktinformationen

Ein letztes Beispiel: Stellen Sie sich vor, Sie haben eine Kontaktliste, die Sie von einer Website kopiert und eingefügt haben:

contacts <- tribble(
  ~field, ~value,
  "name", "Jiena McLellan",
  "company", "Toyota", 
  "name", "John Smith", 
  "company", "google", 
  "email", "[email protected]",
  "name", "Huxley Ratcliffe"
)

Die tabellarische Darstellung dieser Liste ist recht schwierig, da es keine Variable gibt, die angibt, welche Daten zu welchem ​​Kontakt gehören. Wir können dies beheben, indem wir beachten, dass die Daten jedes neuen Kontakts mit „Name“ beginnen. Daher können wir eine eindeutige Kennung erstellen und diese jedes Mal um eins erhöhen, wenn die Feldspalte den Wert „Name“ enthält:

contacts <- contacts %>% 
  mutate(
    person_id = cumsum(field == "name")
  )
contacts

#> # A tibble: 6 x 3
#>   field   value            person_id
#>   <chr>   <chr>                <int>
#> 1 name    Jiena McLellan           1
#> 2 company Toyota                   1
#> 3 name    John Smith               2
#> 4 company google                   2
#> 5 email   [email protected]          2
#> 6 name    Huxley Ratcliffe         3

Da wir nun für jeden Kontakt eine eindeutige ID haben, können wir das Feld und den Wert in Spalten umwandeln:

contacts %>% 
  pivot_wider(names_from = field, values_from = value)

#> # A tibble: 3 x 4
#>   person_id name             company email          
#>       <int> <chr>            <chr>   <chr>          
#> 1         1 Jiena McLellan   Toyota  <NA>           
#> 2         2 John Smith       google  [email protected]
#> 3         3 Huxley Ratcliffe <NA>    <NA>

Abschluss

Meine persönliche Meinung ist, dass das neue Konzept aufgeräumter Wirklich intuitiver und in der Funktionalität den Legacy-Funktionen deutlich überlegen spread() и gather(). Ich hoffe, dieser Artikel hat Ihnen geholfen, damit umzugehen pivot_longer() и pivot_wider().

Source: habr.com

Kommentar hinzufügen