对数据帧中的每个单元格应用条件替换函数。

问题描述 投票:0回答:1

我试图在R中通过检查每个值是否存在于一个特定的列表中,如果存在,则保留它,来子集一个数据框。例如在下面的数据框中,我怎样才能将它子集为只包含1、3和4这三个值呢?

x <- data.frame(A = sample(1:5, 5),
                B = sample(1:5, 5),
                C = sample(1:5, 5))
  A B C
1 2 2 1
2 3 3 3
3 1 4 4
4 4 5 2
5 5 1 5

我怎样才能将它子集到只包含1,3和4这三个值,结果如下:

  A B C
1 1
2 3 3 3
3 4 4
4 4 
5 1 

缺少的值如何处理并不重要 - 如果这样更容易的话,可以将它们改为NA。从浏览类似的问题来看,似乎lapply可能会做到这一点,但作为一个新手,我很难将我所看到的应用到这个场景中。

r dataframe subset
1个回答
1
投票
set.seed(47)
x <- data.frame(A = sample(1:5, 5),
                B = sample(1:5, 5),
                C = sample(1:5, 5))

# with lapply
keep_vals = c(1, 3, 4)
x[] = lapply(x, function(y) {
  y[! y %in% keep_vals] = NA
  return(y)
})

x
#    A  B  C
# 1  3  1  1
# 2  1 NA NA
# 3 NA NA  4
# 4  4  3 NA
# 5 NA  4  3

或者用for循环。

set.seed(47)  # reset data
x <- data.frame(A = sample(1:5, 5),
                B = sample(1:5, 5),
                C = sample(1:5, 5))

keep_vals = c(1, 3, 4)
for (i in 1:ncol(x)) {
  x[, i][!x[, i] %in% keep_vals] <- NA
}
x
#    A  B  C
# 1  3  1  1
# 2  1 NA NA
# 3 NA NA  4
# 4  4  3 NA
# 5 NA  4  3

循环: dplyr

x %>% mutate_all(
  ~replace(., !. %in% keep_vals, NA)
)
#    A  B  C
# 1  3  1  1
# 2  1 NA NA
# 3 NA NA  4
# 4  4  3 NA
# 5 NA  4  3

0
投票

使用 dplyr::bind_rows

do.call(bind_rows,apply(x,1, function(a) a[a %in% c(1,3,4)]))

# A tibble: 5 x 3
      A     B     C
  <int> <int> <int>
1     4    NA    NA
2     1     1     1
3     3     3    NA
4    NA    NA     4
5    NA     4     3

0
投票

将每一行折叠成匹配的数字,并调整每个 lengthncol. 假设你想 "左对齐 "你的数字,如你的预期输出所示。

d <- setNames(as.data.frame(t(apply(d, 1, function(x) {
  x <- x[x %in% c(1, 3, 4)]
  `length<-`(x, ncol(d))
}))), names(d))
d
#    A  B  C
# 1  1 NA NA
# 2  3  3  3
# 3  1  4  4
# 4  4 NA NA
# 5 NA NA NA

由于 apply 抛出一个矩阵,我们告诉R,我们要的是矩阵的 t姿势 as.data.framesetNames 来恢复这些。

注意: 我修改了你的示例数据的第5行,使其不包含任何匹配的数字,这样就不会太容易。


数据

d <- read.table(text="A B C
1 2 2 1
2 3 3 3
3 1 4 4
4 4 5 2
5 5 2 5", header=TRUE)
© www.soinside.com 2019 - 2024. All rights reserved.