2013-03-05 13 views
7

Próbując odpowiedzieć na a question wcześniej, natknąłem się na problem, który wydawał się być prosty, ale nie mogłem zrozumieć.Używaj nazw obiektów na liście w lapply/ldply

Jeśli mam listę dataframes:

df1 <- data.frame(a=1:3, x=rnorm(3)) 
df2 <- data.frame(a=1:3, x=rnorm(3)) 
df3 <- data.frame(a=1:3, x=rnorm(3)) 

df.list <- list(df1, df2, df3) 

że chcę rbind razem, mogę wykonać następujące czynności:

df.all <- ldply(df.list, rbind) 

Jednakże chcę innej kolumny, która identyfikuje, które data.frame każdego przyszedł rząd. Spodziewałem się, że będę mógł użyć metody deparse(substitute(x)) (here i innych), aby uzyskać nazwę odpowiedniego data.frame i dodać kolumnę. W ten sposób zbliżyłem go:

fun <- function(x) { 
    name <- deparse(substitute(x)) 
    x$id <- name 
    return(x) 
} 
df.all <- ldply(df.list, fun) 

Które zwraca

a   x  id 
1 1 1.1138062 X[[1L]] 
2 2 -0.5742069 X[[1L]] 
3 3 0.7546323 X[[1L]] 
4 1 1.8358605 X[[2L]] 
5 2 0.9107199 X[[2L]] 
6 3 0.8313439 X[[2L]] 
7 1 0.5827148 X[[3L]] 
8 2 -0.9896495 X[[3L]] 
9 3 -0.9451503 X[[3L]] 

Tak oczywiście każdy element listy nie zawierają nazwę Myślę, że tak. Czy ktoś może zaproponować sposób, aby uzyskać to, czego się spodziewałem (pokazane poniżej)?

a   x id 
1 1 1.1138062 df1 
2 2 -0.5742069 df1 
3 3 0.7546323 df1 
4 1 1.8358605 df2 
5 2 0.9107199 df2 
6 3 0.8313439 df2 
7 1 0.5827148 df3 
8 2 -0.9896495 df3 
9 3 -0.9451503 df3 
+1

nie dokładnie odpowiedź, ale może być zainteresowany w różnych metod stosowanych [tutaj] (http://stackoverflow.com/q/15162197/324364). – joran

+1

Strzelanie sobie w stopę, nie używając nazwanej listy. –

Odpowiedz

9

Określ swoją listę z nazwiskami i powinien dać ci kolumny .id z nazwą data.frame

df.list <- list(df1=df1, df2=df2, df3=df3) 
df.all <- ldply(df.list, rbind) 

wyjściowa:

.id a   x 
1 df1 1 1.84658809 
2 df1 2 -0.01177462 
3 df1 3 0.58579469 
4 df2 1 -0.64748756 
5 df2 2 0.24384614 
6 df2 3 0.59012676 
7 df3 1 -0.63037679 
8 df3 2 -1.17416295 
9 df3 3 1.09349618 

Następnie można poznać nazwę data.frame z kolumny df.all$.id

Edytuj: Zgodnie komentarzu @Gary Weissman, jeżeli chcesz automatycznie wygenerować nazwy można zrobić

names(df.list) <- paste0('df',seq_along(df.list) 
+0

Pisałem to samo z wyjątkiem 'do.call (rbind, df.list)' zamiast 'ldply', która również daje oryginalny wiersz – N8TRO

+2

Jedyną wadą tego podejścia jest to, że musisz ręcznie wpisać nazwy wszystkich twoich ramek danych.Czy możesz zrobić coś jak' names (df.list) <- paste0 ('df', seq_along (df.list)) ' –

+0

+1 To jest naprawdę pomocne - w gruncie rzeczy odpowiedź na moje pytanie brzmi" Zrób listę nazwaną "- ale doceniam, że poszłaś dalej! – alexwhan

3

Korzystanie z bazy tylko można było spróbować czegoś takiego:

dd <- lapply(seq_along(df.list), function(x) cbind(df_name = paste0('df',x),df.list[[x]])) 

do.call(rbind,dd) 
+0

@joran próbowałeś? wygląda na to, że działa dobrze na moim komputerze. –

+0

Heh. Próbuję go wypróbować, ale to było zanim naprawdę zakończyłeś edycję.Przez jakiś czas miałeś tylko linię "lapply" (i inną wersję zbyt boot), która z pewnością nie działała. – joran

+0

ah przepraszam, moja przeglądarka była zamrożona, a moje modyfikacje zostały zmanipulowane ;-( –

2

w definicji, df.list nie mają nazwy, jednak nawet wtedy deparse substytut idiom nie wydaje się działać easilty (jak lapply wzywa .Internal(lapply(X, FUN)) - trzeba by szukać u źródła, czy nazwa obiektu był dostępny i jak się to

Coś

names(df.list) <- paste('df', 1:3, sep = '') 

foo <- function(n, .list){ 
     .list[[n]]$id <- n 
     .list[[n]] 
     } 

    a   x id 
1 1 0.8204213 a 
2 2 -0.8881671 a 
3 3 1.2880816 a 
4 1 -2.2766111 b 
5 2 0.3912521 b 
6 3 -1.3963381 b 
7 1 -1.8057246 c 
8 2 0.5862760 c 
9 3 0.5605867 c 
2

jeśli chcesz używać function zamiast deparse(substitute(x)) użytku match.call() i chcesz drugi argument, upewniając się, aby przekształcić go character

name <- as.character(match.call()[[2]]) 
Powiązane problemy