Slovník | Vyhledávání | Mapa webu
 
Základy informatiky pro biologyAnalýza dat v R Úprava a transformace dat v R Reorganizace datových tabulek

Logo Matematická biologie

Reorganizace datových tabulek

V analýze dat se v případě výskytu opakovaných měření (pozorování v čase, případně technické replikáty) setkáte s konceptem "široká vs. dlouhá data".

  • široká data - pokud každé opakování reprezentuje samostatný sloupec
  • dlouhá data - pokud každé opakování reprezentuje samostatný řádek

Představme si například měření nejakého krevního parametru x u pacienta v čase 0, 12 a 24 hodin od začátku léčby.

Datová tabulka těchto měření bude ve formátu "širokém" vypadat asi takhle:

> set.seed(12)

> mojedata <- data.frame (pacient=c("P1", "P2", "P3", "P4", "P5"), x.T0 = rnorm(5), x.T12 = rnorm(5), x.T24 = rnorm(5))
> mojedata

  pacient       x.T0      x.T12       x.T24
1      P1 -1.4805676 -0.2722960 -0.77771958
2      P2  1.5771695 -0.3153487 -1.29388230
3      P3 -0.9567445 -0.6282552 -0.77956651
4      P4 -0.9200052 -0.1064639  0.01195176
5      P5 -1.9976421  0.4280148 -0.15241624

 

Mnoho funkcí ale vyžaduje, aby byla data seřazena ve formátu dvou sloupců, z nichž první obsahuje hodnoty a další kategorie - to jsou tzv. dlouhá data. Tento formát můžeme vytvořit pomocí funkce stack():
> sdat  <- stack(mojedata)
Warning message:
In stack.data.frame(mojedata) : non-vector columns will be ignored

Funkce proměnila pouze numerické sloupce, první sloupec proto ignorovala a vypsala upozorňení.

> sdat
        values   ind
1  -1.48056759  x.T0
2   1.57716947  x.T0
3  -0.95674448  x.T0
4  -0.92000525  x.T0
5  -1.99764210  x.T0
6  -0.27229604 x.T12
7  -0.31534871 x.T12
8  -0.62825524 x.T12
9  -0.10646388 x.T12
10  0.42801480 x.T12
11 -0.77771958 x.T24
12 -1.29388230 x.T24
13 -0.77956651 x.T24
14  0.01195176 x.T24
15 -0.15241624 x.T24


V případě, že náš datový soubor obsahuje i numerické sloupce které nechceme transformovat (například věk pacienta), určíme ty pro transorfmaci pomocí parametru select:

> mojedata$vek <- c(30,45,53,48,60)

> sdat2 <- stack(mojedata, select = names(mojedata)[-c(1,5)])

> sdat2
        values   ind
1  -1.48056759  x.T0
2   1.57716947  x.T0
3  -0.95674448  x.T0
4  -0.92000525  x.T0
5  -1.99764210  x.T0
6  -0.27229604 x.T12
7  -0.31534871 x.T12
8  -0.62825524 x.T12
9  -0.10646388 x.T12
10  0.42801480 x.T12
11 -0.77771958 x.T24
12 -1.29388230 x.T24
13 -0.77956651 x.T24
14  0.01195176 x.T24
15 -0.15241624 x.T24

 

Funkce unstack() data převede na původní formát, ale pozor, již zde nenalezneme ty parametry, které jsme první proměnou ztratili (v našem případě sloupec se jménem pacienta):

> unstack(sdat2)
        x.T0      x.T12       x.T24
1 -1.4805676 -0.2722960 -0.77771958
2  1.5771695 -0.3153487 -1.29388230
3 -0.9567445 -0.6282552 -0.77956651
4 -0.9200052 -0.1064639  0.01195176
5 -1.9976421  0.4280148 -0.15241624

Dalším způsobem je použít funkci melt() z balíku reshape.

> melt(mojedata, id.vars=c("pacient","vek"))
   pacient vek variable       value
1       P1  30     x.T0 -1.48056759
2       P2  45     x.T0  1.57716947
3       P3  53     x.T0 -0.95674448
4       P4  48     x.T0 -0.92000525
5       P5  60     x.T0 -1.99764210
6       P1  30    x.T12 -0.27229604
7       P2  45    x.T12 -0.31534871
8       P3  53    x.T12 -0.62825524
9       P4  48    x.T12 -0.10646388
10      P5  60    x.T12  0.42801480
11      P1  30    x.T24 -0.77771958
12      P2  45    x.T24 -1.29388230
13      P3  53    x.T24 -0.77956651
14      P4  48    x.T24  0.01195176
15      P5  60    x.T24 -0.15241624

Zpětně data proměníme v široký formát funkcí cast():

> cast(melt(mojedata, id.vars=c("pacient","vek")))
  pacient vek       x.T0      x.T12       x.T24
1      P1  30 -1.4805676 -0.2722960 -0.77771958
2      P2  45  1.5771695 -0.3153487 -1.29388230
3      P3  53 -0.9567445 -0.6282552 -0.77956651
4      P4  48 -0.9200052 -0.1064639  0.01195176
5      P5  60 -1.9976421  0.4280148 -0.15241624

Představme si, že neměříme pouze jednu, ale dvě proměnné v čase. Funkce stack() nebo melt() jsou omezeny, protože neumí rozlišit více proměnných.

> set.seed(123)

> mojedata$y.T0 <- rnorm(5); mojedata$y.T12 <- rnorm(5)mojedata$y.T24 <- rnorm(5)

Přeměna dat širokých na dlouhá se pak provede pomocí funkce reshape(). Její parametry jsou:

data - datová tabulka, která se má změnit
idvar - vektor názvů proměnných, které se mají opakovat (v našem případě věk a jméno pacienta)
varying - které proměnné dlouhého formátu třeba přeuspořádat do širokého formátu
direction - který směr transformace požadujeme

> mojedatares <- reshape(data = mojedata, idvar = c("pacient","vek"), varying = c("x.T0","y.T0","x.T12","y.T12","x.T24","y.T24"), direction = "long")

> mojedatares
          pacient vek time           x           y
P1.30.T0       P1  30   T0 -1.48056759 -0.56047565
P2.45.T0       P2  45   T0  1.57716947 -0.23017749
P3.53.T0       P3  53   T0 -0.95674448  1.55870831
P4.48.T0       P4  48   T0 -0.92000525  0.07050839
P5.60.T0       P5  60   T0 -1.99764210  0.12928774
P1.30.T12      P1  30  T12 -0.27229604  1.71506499
P2.45.T12      P2  45  T12 -0.31534871  0.46091621
P3.53.T12      P3  53  T12 -0.62825524 -1.26506123
P4.48.T12      P4  48  T12 -0.10646388 -0.68685285
P5.60.T12      P5  60  T12  0.42801480 -0.44566197
P1.30.T24      P1  30  T24 -0.77771958  1.22408180
P2.45.T24      P2  45  T24 -1.29388230  0.35981383
P3.53.T24      P3  53  T24 -0.77956651  0.40077145
P4.48.T24      P4  48  T24  0.01195176  0.11068272
P5.60.T24      P5  60  T24 -0.15241624 -0.55584113

 

Chceme-li upravit data do širokého formátu, použijeme stejnou funkci, ale definujeme jiné parametry:

v.names - které proměnné dlouhého formátu třeba uspořádat do širokého formátu (x,y)

timevar - proměnná označující opakování (time)

> reshape(data = mojedatares, idvar = c("pacient","vek"), v.names = c("x","y"), direction = "wide", timevar="time")
         pacient vek       x.T0        y.T0      x.T12
P1.30.T0      P1  30 -1.4805676 -0.56047565 -0.2722960
P2.45.T0      P2  45  1.5771695 -0.23017749 -0.3153487
P3.53.T0      P3  53 -0.9567445  1.55870831 -0.6282552
P4.48.T0      P4  48 -0.9200052  0.07050839 -0.1064639
P5.60.T0      P5  60 -1.9976421  0.12928774  0.4280148
              y.T12       x.T24      y.T24
P1.30.T0  1.7150650 -0.77771958  1.2240818
P2.45.T0  0.4609162 -1.29388230  0.3598138
P3.53.T0 -1.2650612 -0.77956651  0.4007715
P4.48.T0 -0.6868529  0.01195176  0.1106827
P5.60.T0 -0.4456620 -0.15241624 -0.5558411

Seřazení probíhá s využitím vektorů a indexace.

Seřaďme náš soubor mojedata podle věku pacientů od nejmladšího po nejstaršího:

> mojedata[order(mojedata$vek),]
  pacient       x.T0      x.T12       x.T24 vek        y.T0
1      P1 -1.4805676 -0.2722960 -0.77771958  30 -0.56047565
2      P2  1.5771695 -0.3153487 -1.29388230  45 -0.23017749
4      P4 -0.9200052 -0.1064639  0.01195176  48  0.07050839
3      P3 -0.9567445 -0.6282552 -0.77956651  53  1.55870831
5      P5 -1.9976421  0.4280148 -0.15241624  60  0.12928774
       y.T12      y.T24
1  1.7150650  1.2240818
2  0.4609162  0.3598138
4 -0.6868529  0.1106827
3 -1.2650612  0.4007715
5 -0.4456620 -0.5558411

Nyní seřaďme podle věku a podle proměnné x.T0 - také od největších hodnot po nejmenší:

> mojedata[order(mojedata$vek, mojedata$x.T0),]
  pacient       x.T0      x.T12       x.T24 vek        y.T0
1      P1 -1.4805676 -0.2722960 -0.77771958  30 -0.56047565
2      P2  1.5771695 -0.3153487 -1.29388230  45 -0.23017749
4      P4 -0.9200052 -0.1064639  0.01195176  48  0.07050839
3      P3 -0.9567445 -0.6282552 -0.77956651  53  1.55870831
5      P5 -1.9976421  0.4280148 -0.15241624  60  0.12928774
       y.T12      y.T24
1  1.7150650  1.2240818
2  0.4609162  0.3598138
4 -0.6868529  0.1106827
3 -1.2650612  0.4007715
5 -0.4456620 -0.5558411

 
vytvořil Institut biostatistiky a analýz Lékařské fakulty Masarykovy univerzity