2011-08-16 9 views
13

Mam listę ramek danych, które ostatecznie chcę scalić, zachowując rejestr ich oryginalnej nazwy ramki danych lub indeksu listy. Umożliwi mi to podzbiór itd. We wszystkich wierszach. Aby to osiągnąć, chciałbym dodać nową zmienną "id" do każdej ramki danych, która zawiera nazwę/indeks ramki danych, do której należy.Ramki danych na liście; dodawanie nowej zmiennej o nazwie ramka danych

Edytuj: "W moim prawdziwym kodzie zmienne ramek danych są tworzone z odczytu wielu plików przy użyciu następującego kodu, więc nie mam rzeczywistych nazw tylko tych z listy" files.to.read ", których nie jestem pewien jeśli będą one wyrównać z rzędu dataframe:

mylist <- llply(files.to.read, read.csv) 

kilka metod zostały wyróżnione w kilku wypowiedzi: Working-with-dataframes-in-a-list-drop-variables-add-new-ones i Using-lapply-with-changing-arguments

próbowałem dwa podobne sposoby, pierwszy z użyciem listy index:

df1 <- data.frame(x=c(1:5),y=c(11:15)) 
df2 <- data.frame(x=c(1:5),y=c(11:15)) 
mylist <- list(df1,df2) 

# Adds a new coloumn 'id' with a value of 5 to every row in every dataframe. 
# I WANT to change the value based on the list index. 
mylist1 <- lapply(mylist, 
    function(x){ 
     x$id <- 5 
     return (x) 
    } 
) 
#Example of what I WANT, instead of '5'. 
#> mylist1 
#[[1]] 
    #x y id 
#1 1 11 1 
#2 2 12 1 
#3 3 13 1 
#4 4 14 1 
#5 5 15 1 
# 
#[[2]] 
    #x y id 
#1 1 11 2 
#2 2 12 2 
#3 3 13 2 
#4 4 14 2 
#5 5 15 2 

Druga próba przekazania nazw() listy.

# I WANT it to add a new coloumn 'id' with the name of the respective dataframe 
# to every row in every dataframe. 
mylist2 <- lapply(names(mylist), 
    function(x){ 
     portfolio.results[[x]]$id <- "dataframe name here" 
     return (portfolio.results[[x]]) 
    } 
) 
#Example of what I WANT, instead of 'dataframe name here'. 
# mylist2 
#[[1]] 
    #x y id 
#1 1 11 df1 
#2 2 12 df1 
#3 3 13 df1 
#4 4 14 df1 
#5 5 15 df1 
# 
#[[2]] 
    #x y id 
#1 1 11 df2 
#2 2 12 df2 
#3 3 13 df2 
#4 4 14 df2 
#5 5 15 df2 

Ale nazwy() funkcja nie działa na liście dataframes; zwraca NULL. Czy mogę użyć seq_along (mylist) w pierwszym przykładzie.

Wszelkie pomysły lub lepszy sposób obsłużyć cały „połączyć ze źródłem id”

Edit - Dodany Rozwiązanie poniżej: I zostały wdrożone rozwiązanie korzystając Hadleys sugestie i sugerować Tommy'ego, który wygląda mniej więcej tak.

files.to.read <- list.files(datafolder, pattern="\\_D.csv$", full.names=FALSE) 
mylist <- llply(files.to.read, read.csv) 
all <- do.call("rbind", mylist) 
all$id <- rep(files.to.read, sapply(mylist, nrow)) 

użyłem wektor files.to.read jako identyfikator dla każdego dataframe

zmieniła również z użyciem merge_recurse(), ponieważ była bardzo powolna z jakiegoś powodu.

all <- merge_recurse(mylist) 

Dziękuję wszystkim.

Odpowiedz

16

Osobiście uważam, że łatwiej jest dodać nazwiska po upadku:

df1 <- data.frame(x=c(1:5),y=c(11:15)) 
df2 <- data.frame(x=c(1:5),y=c(11:15)) 
mylist <- list(df1 = df1, df2 = df2) 

all <- do.call("rbind", mylist) 
all$id <- rep(names(mylist), sapply(mylist, nrow)) 
+0

Dzięki nie byłem pewien, czy zawalenie zachowałoby zamówienie. Zwijam listę, aby użyć qplot() i określić podzbiór za pomocą $ id. Jednak bardzo powoli się zwalnia, więc jestem otwarty na inne opcje. –

+0

Wow, użyłem rbind() zamiast merge_recurse() w moim rzeczywistym kodzie, a całkowity czas zmniejszył się z ~ 10 minut do 10 sekund. –

2

może to sprawić, że ma nazwy, ale jej nie dałeś. To nienazwana lista. Będziesz potrzebował użyć indeksów numerycznych:

> for(i in 1:length(mylist)){ mylist[[i]] <- cbind(mylist[[i]], id=rep(i, nrow(mylist[[i]]))) } 
> mylist 
[[1]] 
    x y id 
1 1 11 1 
2 2 12 1 
3 3 13 1 
4 4 14 1 
5 5 15 1 

[[2]] 
    x y id 
1 1 11 2 
2 2 12 2 
3 3 13 2 
4 4 14 2 
5 5 15 2 
+0

Dzięki. Pomiędzy Tommym, Hadleyem i sobą stworzyłem odpowiednie rozwiązanie. Ostatecznie chciałem, aby nazwy były rozpoznawane w dalszej części procesu. –

8

Twoja pierwsza próba była bardzo bliska. Używając indeksów zamiast wartości, będzie działać. Twoja druga próba nie powiodła się, ponieważ nie nazwałeś elementów na liście.

Oba poniższe rozwiązania wykorzystują fakt, że lapply może przekazywać dodatkowe parametry (mylist) do funkcji.

df1 <- data.frame(x=c(1:5),y=c(11:15)) 
df2 <- data.frame(x=c(1:5),y=c(11:15)) 
mylist <- list(df1=df1,df2=df2) # Name each data.frame! 
# names(mylist) <- c("df1", "df2") # Alternative way of naming... 

# Use indices - and pass in mylist 
mylist1 <- lapply(seq_along(mylist), 
     function(i, x){ 
         x[[i]]$id <- i 
         return (x[[i]]) 
     }, mylist 
) 

# Now the names work - but I pass in mylist instead of using portfolio.results. 
mylist2 <- lapply(names(mylist), 
    function(n, x){ 
     x[[n]]$id <- n 
     return (x[[n]]) 
    }, mylist 
) 
+0

Dzięki za odpowiedź na oba przedmioty. Zmieniłem moje pytanie, stwierdzając, że nie mam nazw, ale tak naprawdę to robię. Konwertowanie pliku files.to.read na listę pozwala mi przypisać każdemu elementowi listy odpowiednią nazwę, pod warunkiem, że są poprawnie wyrównane ... Nie widziałem lasu dla drzew! –

1

dlply forma funkcja plyr pakiet może być odpowiedź:

library('plyr') 
df1 <- data.frame(x=c(1:5),y=c(11:15)) 
df2 <- data.frame(x=c(1:5),y=c(11:15)) 
mylist <- list(df1 = df1, df2 = df2) 

all <- ldply(mylist)