删除行,直到列在多个数据框中相同

Remove rows until columns are identical over multiple data frames

我有 4 个 data frames 名为 w, x, y, z,每个都有 3 列和相同的列名。我现在执行一个删除行的操作,直到名为 Type 的列在所有四个数据框中都相同。

为了实现这一点,我使用了带有以下代码的 while 循环:


list_df <- list(z, w, x, y)
tmp <- lapply(list_df, `[[`, 'Type')
i <- as.integer(as.logical(all(sapply(tmp, function(x) all(x == tmp[[1]])))))
                
while (i == 0) {
                  
 z <- z[(z$Type %in% x$Type),]
 y <- y[(y$Type %in% x$Type),]
 w <- w[(w$Type %in% x$Type),]
                      
 z <- z[(z$Type %in% w$Type),]
 y <- y[(y$Type %in% w$Type),]
 x <- x[(x$Type %in% w$Type),]
                     
 z <- z[(z$Type %in% y$Type),]
 x <- x[(x$Type %in% y$Type),]
 w <- w[(w$Type %in% y$Type),]
                      
 x <- x[(x$Type %in% z$Type),]
 w <- w[(w$Type %in% z$Type),]
 y <- y[(y$Type %in% z$Type),]
                     
 list_df <- list(z, w, x, y)
 tmp <- lapply(list_df, `[[`, 'Type')
 i <- as.integer(as.logical(all(sapply(tmp, function(x) all(x == tmp[[1]])))))
 }

在此代码中,为每个数据框的 Type 列创建了一个列表。然后值 i 测试相同性,如果为假则生成 0,如果为真则生成 1。 while loop 然后执行删除不包含在每个数据框中的行,直到 i 变为 1 才停止。

此代码有效,但将其应用于更大的数据可能会导致代码运行时间过长。有人知道如何简化此执行吗?

对于可重现的例子:

w <- structure(list(Type = c("26809D", "28503C", "360254", "69298N", 
"32708V", "680681", "329909", "696978", "32993F", "867609", "51206K", 
"130747"), X1980 = c(NA, NA, NA, 271835, NA, NA, NA, NA, NA, 
NA, NA, NA), X1981 = c(NA, NA, NA, 290314, NA, NA, NA, NA, NA, 
NA, NA, NA)), row.names = c("2", "4", "7", "8", "10", "11", "13", 
"16", "17", "21", "22", "23"), class = "data.frame")

x <- structure(list(Type = c("26809D", "28503C", "360254", "69298N", 
"32708V", "680681", "329909"), X1980 = c(NA, NA, NA, 1026815, 
NA, NA, NA), X1981 = c(NA, NA, NA, 826849, NA, NA, NA)), row.names = c("2", 
"4", "7", "8", "10", "11", "13"), class = "data.frame")

y <- structure(list(Type = c("26809D", "28503C", "360254", "69298N", 
"32708V"), X1980 = c(NA_real_, NA_real_, NA_real_, NA_real_, 
NA_real_), X1981 = c(NA_real_, NA_real_, NA_real_, NA_real_, 
NA_real_)), row.names = c("2", "4", "7", "8", "10"), class = "data.frame")

z <- structure(list(Type = c("26809D", "28503C", "360254", "69298N", 
"32708V", "680681", "329909", "696978", "32993F", "867609", "51206K", 
"130747", "50610H"), X1980 = c(NA, NA, NA, 0.264736101439889, 
NA, NA, NA, NA, NA, NA, NA, NA, NA), X1981 = c(NA, NA, NA, 0.351108848169376, 
NA, NA, NA, NA, NA, NA, NA, NA, NA)), row.names = c("2", "4", 
"7", "8", "10", "11", "13", "16", "17", "21", "22", "23", "24"
), class = "data.frame")

我们假设问题是如何获取 4 个数据框共有的 Type 值,每个数据框都有一个包含唯一值的 Type 列。

形成数据框列表 L,使用 lapply[ 提取 Type 列,并使用 [=] 迭代 merge 21=]:

L <- list(w, x, y, z)
L.Type <- lapply(L, "[", TRUE, "Type", drop = FALSE) # list of DFs w only Type col
Reduce(merge, L.Type)$Type
## [1] "26809D" "28503C" "32708V" "360254" "69298N"

或用此替换最后一行,结果相同,但顺序除外:

Reduce(intersect, L.Type)$Type
## [1] "26809D" "28503C" "360254" "69298N" "32708V"

另一种有点乏味但确实将计算减少到一行的方法是手动迭代 intersect:

intersect(w$Type, intersect(x$Type, intersect(y$Type, z$Type)))
## [1] "26809D" "28503C" "360254" "69298N" "32708V"

另一个例子

示例数据不能很好地说明这一点,因为每个数据框都具有相同的类型值,所以让我们创建另一个示例。 BOD 是一个内置数据框,有 6 行。我们将其分配给 X 并重命名列,以便第一个列的名称为 Type。然后,对于 i 等于 1、2、3、4,我们删除第 i 行,给出 4 个数据框,每个数据框有 5 行,以及所有 4 个共有的 Type 的 2 个值。结果正确显示 5和 7 是唯一常见的 Type 值。

# set up input L, a list of 4 data frames
X <- BOD
names(X) <- c("Type", "X")
L <- lapply(1:4, function(i) X[-i, ])

L.Type <- lapply(L, "[", TRUE, "Type", drop = FALSE)
Reduce(merge, L.Type)$Type
## [1] 5 7