2012-04-06 6 views
8

Mam data.frame, który wygląda tak:Przekształcanie kilka zmiennych szerokości z obsadą

> head(ff.df) 
    .id pio caremgmt prev price surveyNum 
1 1 2  2 1  2   1 
2 1 2  1 2  1   2 
3 1 1  1 2  2   3 
4 1 2  2 1  5   4 
5 1 1  1 1  3   5 
6 1 1  2 2  4   6 

chciałbym przekształcić wszystkie cztery zmienne non-ID szerokości id. Innymi słowy, chcę colnames:

surveyNum pio1 pio2 pio3 caremgmt1 caremgmt2 caremgmt3 prev1 prev2 prev3 price1 price2 price3 

mogę zrobić dla pojedynczej zmiennej:

> cast(ff.df, surveyNum~.id, value=c("pio")) 
    surveyNum 1 2 3 
1   1 2 2 2 
2   2 2 1 2 
3   3 1 2 1 
4   4 2 1 1 
5   5 1 2 2 
6   6 1 2 1 
7   7 1 1 2 
8   8 2 2 1 
9   9 1 1 2 
10  10 1 1 1 
11  11 2 2 1 
12  12 1 2 2 
13  13 1 1 1 
14  14 2 1 1 
15  15 1 2 1 
16  16 2 1 2 
17  17 1 2 2 
18  18 2 1 2 
19  19 1 2 2 
20  20 2 2 2 
21  21 2 1 1 
22  22 1 2 1 
23  23 2 1 1 
24  24 2 1 2 

Ale gdy próbuję go na kilka to po prostu nie całkowicie:

> cast(ff.df, surveyNum~.id, value=c("pio","caremgmt","prev","price")) 
Error in data.frame(data[, c(variables), drop = FALSE], result = data$value) : 
    arguments imply differing number of rows: 72, 0 
In addition: Warning message: 
In names(data) == value : 
    longer object length is not a multiple of shorter object length 

Jakieś wskazówki? Mogę korzystać z bazy (stats) polecenia reshape, ale jestem naprawdę starają się uciec od niego, ponieważ powoduje zbyt dużo ręcznej uraz skóry głowy z włosów ciągnięcie ....

ff.df <- structure(list(.id = c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 3L, 3L, 
3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 
3L, 3L, 3L, 3L, 3L, 3L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
    2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L), pio = structure(c(2L, 
2L, 1L, 2L, 1L, 1L, 1L, 2L, 1L, 1L, 2L, 1L, 1L, 2L, 1L, 2L, 1L, 
2L, 1L, 2L, 2L, 1L, 2L, 2L, 2L, 2L, 1L, 1L, 2L, 1L, 2L, 1L, 2L, 
1L, 1L, 2L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 1L, 1L, 1L, 2L, 2L, 
1L, 2L, 1L, 2L, 2L, 1L, 2L, 1L, 1L, 2L, 2L, 1L, 1L, 2L, 1L, 2L, 
1L, 2L, 2L, 1L, 2L, 1L, 1L), .Label = c("1", "2"), class = "factor"), 
    caremgmt = structure(c(2L, 1L, 1L, 2L, 1L, 2L, 2L, 1L, 1L, 
    2L, 2L, 2L, 2L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 1L, 1L, 2L, 
    1L, 2L, 1L, 2L, 1L, 1L, 2L, 2L, 2L, 1L, 2L, 1L, 2L, 1L, 2L, 
    1L, 2L, 1L, 2L, 1L, 1L, 2L, 1L, 2L, 1L, 2L, 2L, 2L, 2L, 1L, 
    1L, 2L, 1L, 2L, 1L, 1L, 1L, 1L, 2L, 1L, 2L, 2L, 2L, 1L, 1L, 
    1L, 2L, 2L), .Label = c("1", "2"), class = "factor"), prev = structure(c(1L, 
    2L, 2L, 1L, 1L, 2L, 1L, 2L, 2L, 1L, 2L, 2L, 2L, 2L, 1L, 1L, 
    1L, 2L, 2L, 1L, 2L, 1L, 1L, 1L, 2L, 1L, 2L, 2L, 1L, 1L, 1L, 
    2L, 1L, 1L, 2L, 2L, 2L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 1L, 1L, 
    2L, 2L, 2L, 2L, 1L, 2L, 1L, 1L, 2L, 1L, 1L, 1L, 2L, 1L, 2L, 
    1L, 2L, 1L, 1L, 1L, 2L, 2L, 1L, 2L, 2L, 2L), .Label = c("1", 
    "2"), class = "factor"), price = structure(c(2L, 1L, 2L, 
    5L, 3L, 4L, 1L, 5L, 4L, 3L, 1L, 2L, 6L, 6L, 5L, 4L, 6L, 3L, 
    5L, 6L, 3L, 1L, 2L, 4L, 3L, 5L, 2L, 5L, 4L, 5L, 6L, 6L, 4L, 
    6L, 4L, 1L, 2L, 3L, 1L, 2L, 2L, 5L, 1L, 6L, 1L, 3L, 4L, 3L, 
    6L, 5L, 5L, 4L, 4L, 2L, 2L, 2L, 6L, 3L, 1L, 4L, 4L, 5L, 1L, 
    3L, 6L, 1L, 3L, 5L, 1L, 3L, 6L, 2L), .Label = c("1", "2", 
    "3", "4", "5", "6"), class = "factor"), surveyNum = c(1L, 
    2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L, 11L, 12L, 13L, 14L, 
    15L, 16L, 17L, 18L, 19L, 20L, 21L, 22L, 23L, 24L, 1L, 2L, 
    3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L, 11L, 12L, 13L, 14L, 15L, 
    16L, 17L, 18L, 19L, 20L, 21L, 22L, 23L, 24L, 1L, 2L, 3L, 
    4L, 5L, 6L, 7L, 8L, 9L, 10L, 11L, 12L, 13L, 14L, 15L, 16L, 
    17L, 18L, 19L, 20L, 21L, 22L, 23L, 24L)), .Names = c(".id", 
"pio", "caremgmt", "prev", "price", "surveyNum"), row.names = c(NA, 
-72L), class = "data.frame") 
+0

pokrewne pytanie: http://stackoverflow.com/questions/27247078/reshape-multiple-values-at- raz-in-r – landroni

Odpowiedz

13

Myślę, że problem jest że ff.df nie jest jeszcze wystarczająco stopiony. Wypróbuj to:

library(reshape) 

# Melt it down 
ff.melt <- melt(ff.df, id.var = c("surveyNum", ".id")) 

# Note the new "variable" column, which will be combined 
# with .id to make each column header 
head(ff.melt) 

    surveyNum .id variable value 
1   1 1  pio  2 
2   2 1  pio  2 
3   3 1  pio  1 
4   4 1  pio  2 
5   5 1  pio  1 
6   6 1  pio  1 

# Cast it out - note that .id comes after variable in the formula; 
# I think the only effect of that is that you get "pio_1" instead of "1_pio" 
ff.cast <- cast(ff.melt, surveyNum ~ variable + .id) 

head(ff.cast) 

    surveyNum pio_1 pio_2 pio_3 caremgmt_1 caremgmt_2 caremgmt_3 prev_1 prev_2 prev_3 price_1 price_2 price_3 
1   1  2  2  2   2   1   1  1  2  2  2  6  3 
2   2  2  1  2   1   2   2  2  2  1  1  5  5 
3   3  1  2  1   1   2   1  2  1  2  2  5  2 
4   4  2  1  1   2   2   2  1  2  2  5  4  5 
5   5  1  2  2   1   2   1  1  1  1  3  4  4 
6   6  1  2  1   2   1   1  2  1  1  4  2  5 

Czy to ci wystarczy?

Zasadniczo podczas rzutowania zmienne wskazane po prawej stronie formuły rzutowania określają kolumny, które będą wyświetlane w wyniku rzutowania. Podając tylko .id, uważam, że zadałeś cast, aby w jakiś sposób wtłoczyć wszystkie te wektory wartości w zaledwie trzy kolumny - 1, 2 i 3. Topienie danych w całości powoduje utworzenie kolumny variable, która pozwala określić to kombinacja wektorów .id i variable powinna definiować kolumny odlewanej ramki danych.

(przepraszam, jeśli mam być monotonne/pedantyczny! Próbuję pracować go dla siebie, zbyt)

+2

PS: 'reshape2' istnieje już od jakiegoś czasu i jest znacznie szybsze niż oryginał. Sprawdź [ogłoszenie Hadley'a] (https://stat.ethz.ch/pipermail/r-packages/2011/001204.html). Jedyną zmianą, którą musisz wprowadzić w powyższym kodzie, jest zmiana 'cast()' na 'dcast()'. –

+0

To wystarczy. Dzięki! Jeszcze jeden krok na drodze do "oświecenia". –

+0

Re: twój komentarz. Myślę, że chcę go jako ".id ~ variable", ponieważ wpływa na porządkowanie ostatecznego data.frame. –

7

Można to zrobić za pomocą funkcji reshape w base R. Kolejność kolumn jest trochę dziwne, ale można je łatwo naprawić.

reshape(ff.df, direction = 'wide', idvar = "surveyNum", timevar = '.id') 
+0

Zgadzam się i zdecydowanie bardziej jestem zaznajomiony z 'reshape' niż z' cast'em (chociaż używam 'melt' przez cały czas), ale naprawdę gardzę składnią' reshape', więc unikam jej używania. –

+0

Tak. 'reshape' jest genialny, ale z niepotrzebnie złożoną składnią. Może kiedyś napiszę o tym opakowanie. – Ramnath

+0

Zacząłem używać prawie tyle, co w wersji bazowej około miesiąca temu. Składnia jest okropna, ale jest niezwykle potężna. +1 –

4

Można to zrobić przy użyciu dcast od wersji woju data.table tj v1.9.5

library(data.table) 
    ff.cast <- dcast(setDT(ff.df), surveyNum~.id, 
     value.var=c('pio', 'caremgmt', 'prev', 'price')) 
    head(ff.cast,3) 
    # surveyNum 1_pio 2_pio 3_pio 1_caremgmt 2_caremgmt 3_caremgmt 1_prev 2_prev 
    #1:   1  2  2  2   2   1   1  1  2 
    #2:   2  2  1  2   1   2   2  2  2 
    #3:   3  1  2  1   1   2   1  2  1 
    # 3_prev 1_price 2_price 3_price 
    #1:  2  2  6  3 
    #2:  1  1  5  5 
    #3:  2  2  5  2 
Powiązane problemy