gpt4 book ai didi

r - 通过匹配 R 中的嵌套列表来对数据框进行子集化和连接

转载 作者:行者123 更新时间:2023-12-04 23:49:38 25 4
gpt4 key购买 nike

我试图根据每个数据框的列中的元素连接两个数据框 df 和 myData。 df 中的列有意包含嵌套列表,如果嵌套列表中的元素与 myData 的元素匹配,我想加入。我想在 df (左连接)中保留不匹配的行。

这是一个示例,首先在 df 中没有嵌套列表。

df = data.frame(a=1:5)
df$x1= c("a", "b", "g", "a", "a")
str(df)

'data.frame': 5 obs. of 2 variables:
$ a : int 1 2 3 4 5
$ x1: chr "a" "b" "g" "a" ...

myData <- data.frame(x1=c("a", "g", "q"), x2= c("za", "zg", "zq"), stringsAsFactors = FALSE)

现在,我们可以在列 x1 上加入:
#using a for loop
df$x2 <- NA
for(id in 1:nrow(myData)){
df$x2[df$x1 %in% myData$x1[id]] <- myData$x2[id]
}

或者使用 dplyr:
library(dplyr)
df = data.frame(a=1:5)
df$x1= c("a", "b", "g", "a", "a")
df %>%
left_join(myData)

现在,考虑带有嵌套列表的 df。
l1 = list(letters[1:5])
l2 = list(letters[6:10])
df = data.frame(a=1:5)
df$x1= c("a", "b", "g", l1, l2)

正如我们所期望的那样,使用 for 循环无法匹配嵌套列表的元素:
df$x2 <- NA
for(id in 1:nrow(myData)){
df$x2[df$x1 %in% myData$x1[id]] <- myData$x2[id]
}

输出:
df
a x1 x2
1 1 a za
2 2 b <NA>
3 3 g zg
4 4 a, b, c, d, e <NA>
5 5 f, g, h, i, j <NA>

使用 dplyr:
df %>%
left_join(myData)

抛出错误:
Joining by: c("x1", "x2")
Error: cannot join on column 'x1'

我认为解决方案需要取消列出嵌套列表,但尚未理清如何将 unlist 功能应用于上述策略。

我也试过上面的 data.table 包。如何使用 data.table 实现这一点可能是一个额外的问题。但是,就 data.table 处理数据框中的列表而言,我想包括它,因为它可能提供最佳解决方案。

我的实际数据大约有 100,000 行,因此列表与基数 R 的匹配可能是一个性能烦恼(考虑 data.table 的另一个原因?)

Fwiw,在数据框中使用嵌套列表(和其他结构)是我经常在 Python 中做的事情,并且可能有更好的方法来首先在 R 中构建数据。

想法?

最佳答案

这是一个可能的解决方案:

df$x2 <- NA
for(id in 1:nrow(df))
{
df$x2[id] <- ifelse(
length(ff <- myData$x2[which(myData$x1 == intersect(df$x1[[id]], myData$x1))])==0,
NA,
ff)
}

df
# a x1 x2
#1 1 a za
#2 2 b <NA>
#3 3 g zg
#4 4 a, b, c, d, e za
#5 5 f, g, h, i, j zg

上述解决方案存在一些潜在的缺陷。例如,如果我们更改 l1有 2 个可能的匹配项(例如“a”和“g”):
l1 = list(letters[1:7])
df$x1= c("a", "b", "g", l1, l2)

此解决方案不会同时捕获两个匹配项,如下所示:
df$x2 <- NA
for(id in 1:nrow(df))
{
df$x2[id] <- ifelse(
length(ff <- myData$x2[which(myData$x1 == intersect(df$x1[[id]], myData$x1))])==0,
NA,
ff)
}
Warning message:
In myData$x1 == intersect(df$x1[[id]], myData$x1) :
longer object length is not a multiple of shorter object length

如果需要,您可以修改它以允许多个匹配。这里有两种不同的方法来做到这一点,一种使用 paste一个使用 list以你在问题中所做的方式。
df$x2 <- NA
for(id in 1:nrow(df))
{
df$x2[id] <-
paste(if (length(ff <- myData$x2[which(myData$x1 %in% intersect(df$x1[[id]], myData$x1))])==0)
NA else
ff, collapse=", ")
}


df$x2 <- NA
for(id in 1:nrow(df))
{
df$x2[id] <-
list(if (length(ff <- myData$x2[which(myData$x1 %in% intersect(df$x1[[id]], myData$x1))])==0)
NA else
ff)
}

两者都将返回以下内容,但底层结构会有所不同:
  a                  x1     x2
1 1 a za
2 2 b NA
3 3 g zg
4 4 a, b, c, d, e, f, g za, zg
5 5 f, g, h, i, j zg

关于r - 通过匹配 R 中的嵌套列表来对数据框进行子集化和连接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25613547/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com