为什么R中的grepl每隔两行删除一次(虽然没有指定)

Why does grepl in R delete every second row (although this is not specified)

我想为 R 中的分析准备多个数据帧。 其中一些确实在第一行(类型 1)中包含变量标签(= 字符串),有些则不包含(类型 2)。请注意,我指的不是第一行的 header。 所有其他行都包含数值。

我的输入数据帧: 类型 1:

x-axis y-axis

0     200  
5     299
4     314
17    117

类型 2:

0     200  
5     299
4     314
17    117

最后,我想要在第一行中包含所有没有这些字符串的数据框。 两种类型的预期输出:

0     200  
5     299
4     314
17    117

因为我不想手动检查哪些数据帧包含字符串,所以我想 运行 一个跨所有数据帧的代码,删除 "string row".

我注意到有些代码会从不包含该字符串的数据框中删除所有数据。 所以,我现在使用以下代码来防止这个问题:

df_new <- df[!grepl("x-axis", df) , ]

对于没有这些字符串的数据帧,这是完美的(=没有任何反应)。 但是,对于包含这些字符串的数据帧,R 不仅会删除这一行(很棒),还会每隔一行删除一次。

有人知道解决方案吗?

如果您在 data.frame 上调用 grepl,它将 return 按列而不是单元格显示结果。

df <- data.frame('a' = c('th', 'the', 'tre', 'test'),
                 'b' = c('cat', 'cart', 'ca', 'fat'),
                 'c' = c('re', 'awe', 'io', 'ko'),
                 stringsAsFactors = FALSE)

grepl('cat', df)
[1] FALSE  TRUE FALSE

如果您只想搜索一列,请使用@AndrewGustar 的解决方案并将该列传递给 grepl:

grepl('cat', df$b)

如果你想获取在任何地方都有值的行,按行应用 apply:

apply(df, 1, function(x) sum(grepl('cat', x)))

或删除包含该值的行:

df[!apply(df, 1, function(x) sum(grepl('cat', x))),]

正如@AndrewGustar 所说,您应该将列传递给 grepl,而不是整个 data.frame。但多一点解释也可能对这里有所帮助。

grepl 的第二个参数通常应该是字符向量。但如果不是,则 R 将尝试使用 as.character 将其强制转换为一个。让我们做一个虚拟例子来看看它是如何工作的:

df = data.frame(V1=c('x', rep('foo',9)), V2 = 1:10, stringsAsFactors = F)
    # V1 V2
# 1    x  1
# 2  foo  2
# 3  foo  3
# 4  foo  4
# 5  foo  5
# 6  foo  6
# 7  foo  7
# 8  foo  8
# 9  foo  9
# 10 foo 10

现在,如果我们as.character(df),我们得到

[1] "c(\"x\", \"foo\", \"foo\", \"foo\", \"foo\", 
       \"foo\", \"foo\", \"foo\", \"foo\", \"foo\")"
[2] "1:10" 

grepl 作用于此将在这些元素的第一个中找到搜索字符串 'x',但在第二个元素中找不到:

grepl("x", df)
# [1]  TRUE FALSE

这在 df[!grepl("x", df) , ] 中被回收到每两行 return

df_new
#    V1 V2
#2  foo  2
#4  foo  4
#6  foo  6
#8  foo  8
#10 foo 10

所以解决方案是只搜索你想要的列:

df_new <- df[!grepl("x", df$V1) , ]

备注

side-effect as.character return 第二列为 1:10 的一个有趣且可能不直观的 side-effect 是 grepl("1", df) 给出 [1] FALSE TRUE(如预期)。但是,grepl("4", df) returns [1] FALSE FALSE 即使 4 确实出现在第二列中。