如何使用从数据表中提取的值来指定要在 R 中子集化的列?

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

我有一个数据框,我想在一个函数中进行子集化,以便只保留两列均为 1 或 NA 的行。对于 df:

df <- data.frame(a = c(1,1,0,NA,0,1), 
                 b = c(0,1,0,1,0, NA),
                 c = c(0,0,0,0,0,0))

我要:

   a  b  c
2  1  1  0
4 NA  1  0
6  1 NA  0

我遇到的问题是我有很多名称会改变的列。所以这很有效:

subset(df, (is.na(a) | a == 1) & (is.na(b) | b == 1))

但是当列名 'a' 和 'b' 在函数运行期间变成 'd' 和 'f' 时,它会中断。按列索引指定更有效:

subset(df, (is.na(df[,1]) | df[,1] == 1) & (is.na(df[,2]) | df[,2] == 1))

但是很麻烦,如果之前的处理步骤搞砸了并且列“c”在“a”或“b”之前结束,我最终会被错误的列子集。

我还有另一个数据框,指定子集的列名是:

cro_df <- data.frame(pop = c('c1', 'c2'),
                     p1 = c('a', 'd'),
                     p2 = c('b', 'f'))
  pop p1 p2
1  c1  a  d
2  c2  b  f

我希望能够从该数据框中提取列名以用于我的子集函数,例如:

col1 <- cro_df[cro_df[,'pop']=='c1', 'p1']
subset(df, is.na(col1) | col1 == 1)

这将返回一个空数据框。我试过将 col1 变成一个符号和一个没有成功的因素:

subset(df, as.symbol(col1) == 1)
subset(df, sym(col1) == 1)
subset(df, as.factor(col1) == 1)

他们都回来了:

[1] a b c
<0 rows> (or 0-length row.names)

有没有一种方法可以使用第二个数据框 cro_df 将我的列指定为子集?

r subset
2个回答
0
投票

也许这是一个好的开始?

with(cro_df[cro_df$pop == "c1",],
  df[ (is.na(df[[p1]]) | df[[p1]] == 1) & (is.na(df[[p2]]) | df[[p2]] == 1), ]
)
#    a  b c
# 2  1  1 0
# 4 NA  1 0
# 6  1 NA 0

仅供参考,

subset
旨在用于交互式使用,其帮助页面说

Warning:

     This is a convenience function intended for use interactively.
     For programming it is better to use the standard subsetting
     functions like [, and in particular the non-standard evaluation
     of argument ‘subset’ can have unanticipated consequences.

0
投票

您可以使用

filter
包中的
if_all
dplyr

以您认为最适合您的情况的方式选择要过滤的列的名称。在我的例子中,我刚刚创建了一个包含

cols
'a'
的变量
'b'

然后我检查

all_of
cols
filter
行中的列名
if_all
语句是
TRUE
:

library(dplyr) # packageVersion("dplyr") >= 1.1.0

cols <- c('a', 'b')
filter(df, if_all(all_of(cols), \(x) is.na(x) | x == 1))
#>    a  b c
#> 1  1  1 0
#> 2 NA  1 0
#> 3  1 NA 0

如果您为

cols
分配不同的列名,您可以重复使用相同的代码。

© www.soinside.com 2019 - 2024. All rights reserved.