Как использовать lapply для подмножества списка фреймов данных на основе dfs из отдельного списка - PullRequest
1 голос
/ 28 июня 2019

Я начинаю с 2 списков (list_a и list_b), каждый из которых содержит элементы класса df. Моя цель - создать новый список с новым df. Новый df будет содержать все строки из list_a [[1]], которые соответствуют строкам из list_b [[1]] и т. Д. Я могу успешно применить код вручную, но получаю сообщение об ошибке при попытке использовать lapply.

Воспроизводимый пример: 2 списка, каждый с 2 ​​элементами класса df

Список df_a для использования в этом примере

df_a1 <- data.frame(X = c(17,17,18,18), Y=c(105,106,108,109), 
Z=c(3,4,4,6))
df_a2 <- data.frame(X = c(17,17,18,18), Y=c(105,106,108,109), 
Z=c(5,5,4,5))
list_a <- list(df_a1,df_a2)
df_a_list_names<-c("control", "variable")
names(list_a)<-gsub("\\.swc$", "",df_a_list_names)

df_b1 <- data.frame(X= c(17,17,17,18), Y = c(105,106,107,105), 
Z=c(3,4,6,7), I=c(50,50,50,50))
df_b2 <- data.frame(X = c(17,17,17,17), Y = c(105,106,107,108), 
Z=c(5,5,6,7), I=c(75,75,75,75))
list_b <- list(df_b1,df_b2)
df_b_list_names<-c("control", "variable")
names(list_b)<-gsub("\\.txt$", "",df_b_list_names)

код, который работает при ручном применении

list_a[[1]]->fobA  
list_b[[1]]->fobB

new.df<-fobB%>%semi_join(fobA,by="X")%>%
semi_join(fobA,by="Y")%>%
semi_join(fobA,by="Z")
arrange(new.df, Z)->final.df

Результаты работы без ручного управления

data.frame ': 2 шт. из 4 переменных:

$ X: число 17 17

$ Y: число 105 106

$ Z: число 3 4

$ I: число 50 50

Изменено выше как функция

fxn3<-function(x){
new.df<-list_b%>%semi_join(list_a,by="X")%>%
semi_join(list_a,by="Y")%>%
semi_join(list_a,by="Z")
arrange(new.df, Z)->final.df
return(final.df)
}

Здесь я попробовал использовать lapply с пользовательской функцией

lapply(list_a, "fxn3")->fob.final.listHere is the error message 

Я получил следующее сообщение об ошибке

Ошибка в UseMethod ("semi_join"): нет применимого метода для

semi_join применяется к объекту класса "list"

Ответы [ 3 ]

3 голосов
/ 28 июня 2019

Вам не нужно делать semi_join() три раза, вы можете сделать это за один шаг:

library(tidyverse)
map2(.x = list_b, .y = list_a, ~  semi_join(.x, .y, by=c("X", "Y", "Z")))
1 голос
/ 28 июня 2019

Здесь нам нужно выполнить объединение соответствующих наборов данных в каждом list с, чтобы мы могли использовать map2

library(tidyverse)
map2(list_b, list_a, semi_join)
#$control
#   X   Y Z  I
#1 17 105 3 50
#2 17 106 4 50

#$variable
#   X   Y Z  I
#1 17 105 5 75
#2 17 106 5 75

ПРИМЕЧАНИЕ. Здесь мы сначала показали параметр map2


В base R мы можем использовать Map

Map(merge, list_b, list_a)
0 голосов
/ 28 июня 2019

Решение lapply, запрошенное OP, будет выглядеть следующим образом.

lapply(1:2, function(x) merge(list_b[[x]], list_a[[x]]))
# [[1]]
#    X   Y Z  I
# 1 17 105 3 50
# 2 17 106 4 50
# 
# [[2]]
#    X   Y Z  I
# 1 17 105 5 75
# 2 17 106 5 75
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...