2016-03-10 4 views
-1

Я полный noob в R, и я попытался (и повторил), чтобы найти ответ на следующую проблему, но я не смог получить ни одну из предложенных решения, чтобы сделать то, что я заинтересован вR: Слияние списков кадров данных

у меня есть два списка названных элементов, причем каждый элемент, указывающий на кадры данных с идентичными раскладками:.

(EDIT)

df1 <- data.frame(A=c(1,2,3),B=c("A","B","C")) 
df2 <- data.frame(A=c(98,99),B=c("Y","Z")) 
lst1 <- c(X=df1,Y=df2) 
df3 <- data.frame(A=c(4,5),B=c("D","E")) 
lst2 <- c(X=df3) 

(EDIT 2)

S o похоже, что хранение нескольких кадров данных в списке - плохая идея, так как она преобразует кадры данных в списки. Поэтому я пойду искать альтернативный способ хранения набора именованных фреймов данных.

В общем, названия элементов в двух элементах могут частично или полностью перекрываться или полностью отсутствовать.

Я ищу способ объединить два списка в один список:

<some-function-sequence>(lst1, lst2) 
-> 
c(X=rbind(df1,df3),Y=df2) 

-resulting в чем-то вроде этого:

[EDIT: Синтаксис изменен, чтобы правильно отражать желаемый результат (список-о-данных кадров)] $ X АВ Б 3 3 С 4 4 D 5 5 Е

$X.B 
    A B 
1 98 Y 
2 99 Z 

Т.е.:

  • ЕСЛИ списки содержат одинаковые имена элементов, каждый из которых указывает на кадр данных, то я хочу «rbind» строки из этих двух кадров данных и назначить результирующий кадр данных на то же имя элемента в результирующем списке.
  • В противном случае имена элементов и фреймы данных из обоих списков должны быть просто скопированы в результирующий список.

Я попытался решения из ряда обсуждений, таких как:

-but Я не смог найти правильное решение. Основная проблема заключается в том, что кадр данных заканчивается преобразованием в список приложением «mapply/sapply/merge/...» - и обычно также нарезается и/или объединяется способами, которые меня не интересуют. :)

Любая помощь с этим будет высоко оценена!

[РЕШЕНИЕ] Решение, как представляется, изменить использование c(...) при сборе кадров данных в list(...), после чего раствор, предложенный Пьером, кажется, дает желаемый результат.

+0

Потратьте некоторое время, чтобы создать несколько кадров данных примеров. Псевдокод недостаточно специфичен для описания внутренней структуры того, с чем вы работаете. 'c (a = , ..' будет разбивать кадр данных на элементы списка для каждого столбца. Я сомневаюсь, что вы реальные данные отражают это. –

+0

Если у вас есть данные, хранящиеся в списках как в 'list (a = df1, b = df2)', тогда вы можете использовать split и rbind 'lapply (split (c (lst1, lst2), имена (c (lst1, lst2))), функция (lst). call (rbind, lst)) ' –

+0

Спасибо за ваш ответ Pierre. Я попробовал ваше предложение выше, но не смог заставить его работать. Я добавил некоторые данные примера к моему вопросу и результат запуска вашего команду на ней. – RBA

ответ

0

Вот предлагаемое решение с использованием split и c комбинировать подобные термины. Пожалуйста, ознакомьтесь с нижеследующим предостережением:

s <- split(c(lst1, lst2), names(c(lst1,lst2))) 
lapply(s, function(lst) do.call(function(...) unname(c(...)), lst)) 
# $X.A 
# [1] 1 2 3 4 5 
# 
# $X.B 
# [1] "A" "B" "C" "D" "E" 
# 
# $Y.A 
# [1] 98 99 
# 
# $Y.B 
# [1] "Y" "Z" 

Это решение основано на NOT, имеющем факторы как строки. Он не будет вызывать ошибку, но факторы будут преобразованы в числа. Ниже я покажу, как я преобразовал данные для удаления факторов. Дайте мне знать, если вам требуется факторы:

df1 <- data.frame(A=c(1,2,3),B=c("A","B","C"), stringsAsFactors=FALSE) 
df2 <- data.frame(A=c(98,99),B=c("Y","Z"), stringsAsFactors=FALSE) 
lst1 <- c(X=df1,Y=df2) 
df3 <- data.frame(A=c(4,5),B=c("D","E"), stringsAsFactors=FALSE) 
lst2 <- c(X=df3) 

Если данные хранятся в списках можно использовать:

lapply(split(c(lst1, lst2), names(c(lst1,lst2))), function(lst) do.call(rbind, lst)) 
0

Следующее решение, вероятно, не самый эффективный способ. Тем не менее, если я получил вашу проблему право это должно работать;)

# Example data 

# Some vectors 
a <- 1:5 
b <- 3:7 
c <- rep(5, 5) 
d <- 5:1 

# Some dataframes, data1 and data3 have identical column names 
data1 <- data.frame(a, b) 
data2 <- data.frame(c, b) 
data3 <- data.frame(a, b) 
data4 <- data.frame(c, d) 

# 2 lists 
list1 <- list(data1, data2) 
list2 <- list(data3, data4) 

# Loop, wich checks for the dataframe names and rbinds dataframes with the same column names 
final_list <- list1 
used_lists <- numeric() 

for(i in 1:length(list1)) { 

    for(j in 1:length(list2)) { 

    if(sum(colnames(list1[[i]]) == colnames(list2[[j]])) == ncol(list1[[i]])) { 

     final_list[[i]] <- rbind(list1[[i]], list2[[j]]) 
     used_lists <- c(used_lists, j) 

    } 
    } 
} 

# Adding the other dataframes, which did not have the same column names 
for(i in 1:length(list2)) { 

    if((i %in% used_lists) == FALSE) { 

    final_list[[length(final_list) + 1]] <- list2[[i]] 

    } 
} 

# Final list, which includes all other lists 
final_list 
+0

Спасибо за ответ. к сожалению, я получаю следующий результат при запуске вашего кода по моим данным примера: 'list1 <- lst1list2 <- lst2 (...) Ошибка в if (sum (colnames (list1 [[i]]) == colnames (list2 [[j]])) == ncol (list1 [[i]])) {: аргумент имеет длину 0 – RBA

+0

Если вы хотите создать список фреймов данных, вам нужно написать список (df1, df2) вместо c (df1, df2). Если вы это сделаете, мой код должен работать. – JSP

Смежные вопросы