Датафреймы в списке;добавление новой переменной с именем dataframe - PullRequest
15 голосов
/ 16 августа 2011

У меня есть список фреймов данных, которые я в итоге хочу объединить, сохраняя при этом запись их исходного имени фрейма данных или индекса списка. Это позволит мне установить подмножество во всех строках Для этого я хотел бы добавить новую переменную 'id' к каждому фрейму данных, который содержит имя / индекс фрейма данных, которому он принадлежит.

Редактировать: «В моем реальном коде переменные dataframe создаются из чтения нескольких файлов с использованием следующего кода, поэтому у меня нет реальных имен только тех, которые находятся в списке« files.to.read », что я не уверен, если они будут приведены в соответствие с порядком данных:

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

Несколько методов были выделены в нескольких сообщениях: Работа с dataframes-in-a-list-drop-variable-add-new-ones и Использование-lapply-с меняющимися-аргументы

Я пробовал два аналогичных метода, первый из которых использовал список индексов:

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

Вторая попытка передать имена () из списка.

# 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

Но функция names () не работает со списком фреймов данных; возвращает NULL. Могу ли я использовать seq_along (mylist) в первом примере.

Любые идеи или лучший способ справиться со всем «объединением с идентификатором источника»

Правка - Добавлено решение ниже: Я реализовал решение, используя предложение Хэдлиса и подталкивание Томми, которое выглядит примерно так.

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))

Я использовал вектор files.to.read в качестве идентификатора для каждого кадра данных

Я также отказался от использования merge_recurse (), поскольку по какой-то причине он был очень медленным

 all <- merge_recurse(mylist)

Спасибо всем.

Ответы [ 4 ]

18 голосов
/ 16 августа 2011

Лично я думаю, что после коллапса проще добавить имена:

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))
8 голосов
/ 16 августа 2011

Ваша первая попытка была очень близка.Используя индексы вместо значений, это будет работать.Ваша вторая попытка не удалась, потому что вы не назвали элементы в вашем списке.

Оба решения ниже используют тот факт, что lapply может передавать дополнительные параметры (mylist) в функцию.

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
)
2 голосов
/ 16 августа 2011

names() мог бы сработать, у него были имена, но ты его не дал.Это неназванный список.Вам нужно будет использовать числовые индексы:

> 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
1 голос
/ 09 ноября 2014

dlply форма функции plyr Пакет может быть ответом:

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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...