在对数据列表中的数据帧进行多重过滤时,我遇到了麻烦。我的真实数据集非常庞大,因此我如下创建了一个伪造的数据集,以使该问题可复制。
set.seed(1)
df <- data.frame(Cluster=round(runif(2000,1,50)),
Grup = paste0("Group",round(runif(2000,1,10))),
ID = paste0("id",1:2000),
Point1 = round(runif(2000,1,100)),
Point2 = round(runif(2000,1,100)))
Cluster_grup <- list(List1 = data.frame( V1=c(47,35),V2=c(20,35)),
List2 = data.frame(V1=c(10,5,6),V2=c(49,2,46),V3=c(11,12,13)),
List3 = data.frame(V1=c(22,3),V2=c(18,18),V3=c(50,25),V4=c(6,7)))
Grup_info <- list(First = c("Group1","Group7"),
Second = c("Group4","Group5","Group3"),
Third = c("Group10","Group8","Group1","Group6"))
我基本上想对Grup_info
和Cluster_grup
中的数据进行过滤。例如,如果我们采用这两个列表的第一个元素,
Grup_info[[1]]
"Group1" "Group7"
Cluster_grup [[1]]
V1 V2
1 47 20
2 35 35
然后我需要过滤并应用expand.grid
,
df_sorted1 <- df %>% filter(.,Cluster == 47 & Grup=="Group1") %>%
select(.,ID,Point1,Point2)
df_sorted2 <-df %>% filter(.,Cluster == 20 & Grup=="Group7") %>%
select(.,ID,Point1,Point2)
ep1 <- expand.grid(df_sorted1$ID,df_sorted2$ID)
ep2 <- expand.grid(df_sorted1$Point1,df_sorted2$Point1)
ep3 <- expand.grid(df_sorted1$Point2,df_sorted2$Point2)
data.frame(ep1, SumPoint1 = rowSums(ep2),SumPoint2 = rowSums(ep3))
因此,在Cluster == 35
函数内分配filter
时将应用相同的内容。然后,我还将绑定这两个数据帧。
但是您可以看到,组的长度不相等。例如,第三个Grup_info
里面有四个元素,就像第三个Cluster_grup
一样。
最后,我想获得一个列表,其中包括三个数据帧,它们是expand.grid
输出的绑定数据帧。
我实际上可以通过for循环或sapply系列函数来实现它,但是我想知道是否存在诸如tidyverse方法之类的更快解决方案。
答案 0 :(得分:1)
很高兴见到你,maydin
我编写了可能想要的代码。
set.seed(1)
library(dplyr)
library(tidyverse)
library(rlang)
library(data.table)
df <- data.frame(Cluster=round(runif(2000,1,50)),
Grup = paste0("Group",round(runif(2000,1,10))),
ID = paste0("id",1:2000),
Point1 = round(runif(2000,1,100)),
Point2 = round(runif(2000,1,100)))
Cluster_grup <- list(List1 = data.frame( V1=c(47,35),V2=c(20,35)),
List2 = data.frame(V1=c(10,5,6),V2=c(49,2,46),V3=c(11,12,13)),
List3 = data.frame(V1=c(22,3),V2=c(18,18),V3=c(50,25),V4=c(6,7)))
Grup_info <- list(List1 = c("Group1","Group7"),
List2 = c("Group4","Group5","Group3"),
List3 = c("Group10","Group8","Group1","Group6"))
我合并了Cluster_grup
和Grup_info
。
mergeGrp <-
sapply(names(Grup_info), function(x){
material <- Cluster_grup[[ x ]]
colnames(material)<- Grup_info[[x]]
return(material)
})
> mergeGrp
$List1
Group1 Group7
1 47 20
2 35 35
$List2
Group4 Group5 Group3
1 10 49 11
2 5 2 12
3 6 46 13
$List3
Group10 Group8 Group1 Group6
1 22 18 50 6
2 3 18 25 7
我使用RbindList
合并所有结果。
但是,如果您不想那样做,就应该控制自己。
FinalResult = lapply(mergeGrp,function(x){
tidyTest = x %>% tidyr::gather() %>% dplyr::group_by(key)
result = NULL
for (i in 1: NROW(x)){
mate = tidyTest %>% filter(row_number() == i )
condList = apply(mate,1,function(x){
sprintf("( Cluster == %s & Grup == '%s' )",x[2],x[1])
})
filtered = lapply(condList, function(x){
df %>% filter_(x) %>% select(ID,Point1,Point2)}
)
ep1 = filtered %>% purrr::map(.,~.$ID) %>%
as.vector() %>% expand.grid()
ep2 = filtered %>% purrr::map(.,~.$Point1) %>% as.vector() %>%
expand.grid() %>% rowSums()
ep3 = filtered %>% purrr::map(.,~.$Point2) %>% as.vector() %>%
expand.grid() %>% rowSums()
result = rbind(result,data.frame(ep1, SumPoint1 = ep2,SumPoint2 = ep3))
}
return(result)
}
)
#rbindlist(FinalResult)