2015-05-01 7 views
1

Это ответвление более раннего post, в результате чего было обсуждено упрощение моей функции и устранение необходимости объединения фреймов данных, которые являются результатом lapply. Хотя такие инструменты, как dplyr и data.table, устраняют необходимость слияния, я все равно хотел бы знать, как слить в этой ситуации. Я упростил функцию, которая создает список, основанный на этом answer, на мой предыдущий вопрос.Объединение фреймов данных в списке

#Reproducible data 
Data <- data.frame("custID" = c(1:10, 1:20), 
    "v1" = rep(c("A", "B"), c(10,20)), 
    "v2" = c(30:21, 20:19, 1:3, 20:6), stringsAsFactors = TRUE) 

#Split-Apply function 
res <- lapply(split(Data, Data$v1), function(df) { 
    cutoff <- quantile(df$v2, c(0.8, 0.9)) 
    top_pct <- ifelse(df$v2 > cutoff[2], 10, ifelse(df$v2 > cutoff[1], 20, NA)) 
    na.omit(data.frame(custID = df$custID, top_pct)) 
    }) 

Это дает мне следующие результаты:

$A 
    custID top_pct 
1  1  10 
2  2  20 

$B 
    custID top_pct 
1  1  10 
2  2  20 
6  6  10 
7  7  20 

Я хотел результаты, чтобы выглядеть следующим образом:

custID A_top_pct B_top_pct 
1  1  10  10 
2  2  20  20 
3  6  NA  10 
4  7  NA  20 

Какой самый лучший способ попасть? Должен ли я делать какие-то изменения? Если я это сделаю, мне нужно сначала объединить фреймы данных?

Вот мое решение, которое может быть не лучшим. (В реальном приложении, будет больше, чем два кадра данных в списке.)

#Change the new variable name 
names1 <- names(res) 

for(i in 1:length(res)) { 
    names(res[[i]])[2] <- paste0(names1[i], "_top_pct") 
} 

#Merge the results 
res_m <- res[[1]] 
for(i in 2:length(res)) { 
    res_m <- merge(res_m, res[[i]], by = "custID", all = TRUE) 
} 

ответ

3

Вы можете попробовать Reduce с merge

Reduce(function(...) merge(..., by='custID', all=TRUE), res) 
#  custID top_pct.x top_pct.y 
#1  1  10  10 
#2  2  20  20 
#3  6  NA  10 
#4  7  NA  20 

Или, как @Colonel Beauvel предложил, более читаемый подход будет оборачивать его Curry из library(functional)

library(functional) 
Reduce(Curry(merge, by='custID', all=T), res) 
+2

Может быть, даже более читаемым с 'functional' пакета:' Reduce (Карри (слияние, по = 'CustID', all = T), res) ' –

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