R Language
Gegevens hervormen tussen lange en brede formulieren
Zoeken…
Invoering
In R worden gegevens in tabelvorm opgeslagen in gegevensframes . Dit onderwerp behandelt de verschillende manieren om een enkele tabel te transformeren.
Opmerkingen
Handige pakketten
- Hervormen, stapelen en splitsen met data.table
- Geef vorm met behulp van tidyr
- splitstackshape
De hervormingsfunctie
De meest flexibele R-basisfunctie voor het hervormen van gegevens is reshape
. Zie ?reshape
voor de syntaxis.
# create unbalanced longitudinal (panel) data set
set.seed(1234)
df <- data.frame(identifier=rep(1:5, each=3),
location=rep(c("up", "down", "left", "up", "center"), each=3),
period=rep(1:3, 5), counts=sample(35, 15, replace=TRUE),
values=runif(15, 5, 10))[-c(4,8,11),]
df
identifier location period counts values
1 1 up 1 4 9.186478
2 1 up 2 22 6.431116
3 1 up 3 22 6.334104
5 2 down 2 31 6.161130
6 2 down 3 23 6.583062
7 3 left 1 1 6.513467
9 3 left 3 24 5.199980
10 4 up 1 18 6.093998
12 4 up 3 20 7.628488
13 5 center 1 10 9.573291
14 5 center 2 33 9.156725
15 5 center 3 11 5.228851
Merk op dat het data.frame ongebalanceerd is, dat wil zeggen dat eenheid 2 een waarneming mist in de eerste periode, terwijl eenheden 3 en 4 waarnemingen missen in de tweede periode. Merk ook op dat er twee variabelen zijn die variëren over de perioden: tellingen en waarden, en twee die niet variëren: ID en locatie.
Lang tot breed
Om het data.frame om te vormen naar een groot formaat,
# reshape wide on time variable
df.wide <- reshape(df, idvar="identifier", timevar="period",
v.names=c("values", "counts"), direction="wide")
df.wide
identifier location values.1 counts.1 values.2 counts.2 values.3 counts.3
1 1 up 9.186478 4 6.431116 22 6.334104 22
5 2 down NA NA 6.161130 31 6.583062 23
7 3 left 6.513467 1 NA NA 5.199980 24
10 4 up 6.093998 18 NA NA 7.628488 20
13 5 center 9.573291 10 9.156725 33 5.228851 11
Merk op dat de ontbrekende tijdsperioden zijn ingevuld met NA's.
Bij het breed hervormen geeft het argument "v.names" de kolommen aan die in de loop van de tijd variëren. Als de locatievariabele niet nodig is, kan deze worden verwijderd voordat deze wordt gewijzigd met het argument "drop". Door de enige niet-variërende / niet-id kolom uit het data.frame te verwijderen, wordt het argument v.names overbodig.
reshape(df, idvar="identifier", timevar="period", direction="wide",
drop="location")
Breed tot lang
Om lang te hervormen met de huidige df.wide, is een minimale syntaxis
reshape(df.wide, direction="long")
Dit is echter meestal lastiger:
# remove "." separator in df.wide names for counts and values
names(df.wide)[grep("\\.", names(df.wide))] <-
gsub("\\.", "", names(df.wide)[grep("\\.", names(df.wide))])
Nu zal de eenvoudige syntaxis een fout produceren over ongedefinieerde kolommen.
Met kolomnamen die moeilijker zijn voor de functie reshape
om automatisch te parseren, is het soms nodig om het argument 'variërend' toe te voegen dat opnieuw reshape
om bepaalde variabelen in breed formaat te groeperen voor de transformatie naar lang formaat. Dit argument neemt een lijst met vectoren van variabelenamen of indices.
reshape(df.wide, idvar="identifier",
varying=list(c(3,5,7), c(4,6,8)), direction="long")
Bij het lang opnieuw vormgeven kan het argument "v.names" worden gebruikt om de resulterende variërende variabelen te hernoemen.
Soms is de specificatie van de "wisselende" kan worden voorkomen door het gebruik van de "september" argument waarin wordt verteld reshape
welk deel van de naam variabele geeft de waarde argument en die specificeert de tijd argument.
Gegevens hervormen
Vaak komen gegevens in tabellen. Over het algemeen kan men deze tabelgegevens in brede en lange formaten verdelen. In een breed formaat heeft elke variabele zijn eigen kolom.
Persoon | Hoogte (cm] | Leeftijd [jr] |
---|---|---|
Alison | 178 | 20 |
Bob | 174 | 45 |
Carl | 182 | 31 |
Soms is het echter handiger om een lang formaat te hebben, waarin alle variabelen in één kolom staan en de waarden in een tweede kolom.
Persoon | veranderlijk | Waarde |
---|---|---|
Alison | Hoogte (cm] | 178 |
Bob | Hoogte (cm] | 174 |
Carl | Hoogte (cm] | 182 |
Alison | Leeftijd [jr] | 20 |
Bob | Leeftijd [jr] | 45 |
Carl | Leeftijd [jr] | 31 |
Base R en pakketten van derden kunnen worden gebruikt om dit proces te vereenvoudigen. Voor elk van de opties wordt de mtcars
gegevensset gebruikt. Standaard heeft deze dataset een lang formaat. Om de pakketten te laten werken, voegen we de rijnamen in als de eerste kolom.
mtcars # shows the dataset
data <- data.frame(observation=row.names(mtcars),mtcars)
Base R
Er zijn twee functies in base R die kunnen worden gebruikt om te converteren tussen breed en lang formaat: stack()
en unstack()
.
long <- stack(data)
long # this shows the long format
wide <- unstack(long)
wide # this shows the wide format
Deze functies kunnen echter zeer complex worden voor meer geavanceerde gebruikssituaties. Gelukkig zijn er andere opties met pakketten van derden.
Het opgeruimde pakket
Dit pakket gebruikt gather()
om van breed naar lang te converteren en spread()
om van lang naar breed te converteren.
library(tidyr)
long <- gather(data, variable, value, 2:12) # where variable is the name of the
# variable column, value indicates the name of the value column and 2:12 refers to
# the columns to be converted.
long # shows the long result
wide <- spread(long,variable,value)
wide # shows the wide result (~data)
Het data.table pakket
Het pakket data.table breidt de reshape2
functies uit en gebruikt de functie melt()
om van breed naar lang te gaan en dcast()
om van lang naar breed te gaan.
library(data.table)
long <- melt(data,'observation',2:12,'variable', 'value')
long # shows the long result
wide <- dcast(long, observation ~ variable)
wide # shows the wide result (~data)