【问题标题】:Logical indexing failure in RR中的逻辑索引失败
【发布时间】:2013-09-10 16:42:50
【问题描述】:

我试过用内置数据集重现这个问题,但它只发生在我自己的身上。

如果我们随机抽取我的数据子集:

structure(list(ID = structure(c(27L, 1L, 27L, 7L, 5L, 10L, 23L, 
19L, 21L, 26L), .Label = c("AC ", "AJ ", "AT ", "AWY", "BP ", 
"BW ", "CA ", "CK ", "CS ", "DJ ", "EN ", "ES ", "HF ", "HG ", 
"HL ", "HR ", "IP ", "JA ", "JG ", "JN ", "KB ", "KP ", "MJ ", 
"PC ", "RFH", "RPA", "SB ", "SG ", "TM "), class = "factor"), 
TNO = c(30L, 60L, 30L, 10000L, 10000L, 10000L, 120L, 60L, 
120L, 10000L), TNOGroup = structure(c(1L, 1L, 1L, 2L, 2L, 
2L, 2L, 1L, 2L, 2L), .Label = c("Good", "Poor"), class = "factor"), 
x = c(6.15, 7.75, 5.6, 3.05, 3, 4.1, 6, 3.9, 5.85, 3.75), 
View = structure(c(1L, 1L, 2L, 2L, 2L, 2L, 1L, 2L, 1L, 1L
), .Label = c("Binocular", "Monocular"), class = "factor"), 
Prior = structure(c(2L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 1L
), .Label = c("N", "Y"), class = "factor")), .Names = c("ID", 
"TNO", "TNOGroup", "x", "View", "Prior"), row.names = c(169L, 
49L, 24L, 16L, 9L, 4L, 35L, 18L, 164L, 36L), class = "data.frame")

然后尝试删除 ID 的所有实例,该 ID 是两个字符的字符串,例如“SB”:

data2 <- data[!data$ID %in% c("SB"),] # List syntax in case multiple cases

但是,当我检查数据框时,ID 为“SB”的案例仍然存在。当我尝试使用诸如“RPA”之类的三个字符的字符串时,所有具有此 ID 的案例都会按预期删除。

对为什么会发生这种情况有任何见解吗?

【问题讨论】:

  • 尝试使用参数quote = TRUE 打印您的data.frame,以查看任何“CA”值周围是否有空格。 (print(data, quote = TRUE)。如果他们这样做了,那么您最好使用grep 而不是%in%
  • 请使用dput 发布您的数据,这样我们将拥有正确的结构(例如,我们将正确地将ID 作为factorcharacter 列) .粘贴到 R 中也更容易。
  • 你有多余的空间,试试这个:data[!data$ID %in% c("SB "),]
  • 如果您在使用 import 命令去除空白时遇到很多麻烦,您可以在导入后使用例如stringr::str_trim。如果这样做,最简单的方法是为导入设置stringsAsFactors = FALSE,然后在修剪空白后转换为因子。

标签: r indexing dataframe


【解决方案1】:

作为%in% 的替代品,我建议尝试如下grepl

mydf[!grepl("CA", mydf$ID), ]
   ID   TNO TNOGroup    x      View Prior
1  AC    60     Good 5.75 Binocular     Y
2 RFH    60     Good 5.60 Monocular     N
3  BP 10000     Poor 3.00 Monocular     N
4  HG    60     Good 4.30 Binocular     Y
6  IP   120     Poor 5.50 Monocular     N
7  JG    60     Good 3.80 Monocular     Y
9 AWY 10000     Poor 3.70 Monocular     Y

我的怀疑(如果没有实际看到使用dput 提供的数据子集,我无法验证)是"CA" 值周围可能有空格。对于 R,"CA""CA " 不同,即使它们在 data.frame 中看起来可能相同。


如果正在读入的文件中有空格,通常会发生这样的问题。默认情况下,R 在决定是否删除该空格时是保守的,但它包含了逻辑参数 strip.white 以用于read.table 和家人。

因此,您可以通过以下方式避免此问题:

read.csv("yourfile.csv", strip.white = TRUE)

另请注意,这不一定是%in%更安全或更强烈推荐的替代方案。使用 grepl 可能会产生意想不到的后果。例如,如果您有另一个 ID 是 "CAR",那么使用我共享的选项也会匹配。


更新

即使strip.white 也无法解决您的所有问题。如果您的 CSV 引用了所有字符串,并且引号之间存在硬编码的空格,strip.white 将按照预期使用这些空格。

这是一个基本示例。

我们将创建一个 CSV 文件,其中第一行数据包含硬编码的空格,而第二行数据没有。

myTest <- tempfile()
cat(file = myTest, 'A, B, C', 
    '"AA", "BB ", "CC"', 
    '    AA,   BB   , CC', 
    sep = "\n")

现在,使用read.csv 和不带strip.white = TRUE 读取文件并比较输出。

A <- read.csv(myTest)
B <- read.csv(myTest, strip.white = TRUE)
print(A, quote = TRUE)
#          A          B     C
# 1     "AA"     " BB " " CC"
# 2 "    AA" "   BB   " " CC"
print(B, quote = TRUE)
#      A     B    C
# 1 "AA" "BB " "CC"
# 2 "AA"  "BB" "CC"
unlink(myTest)

请注意,在“B”中,对于引号之间的空格未硬编码的行,空格已被适当地修剪,但仍保留在第一行。要解决 那个 问题,您可能需要使用一些正则表达式来去除字符串开头和结尾的空格。

【讨论】:

  • 阿南达,你的怀疑是正确的。创建数据框时,我确定将两个字符的 ID 字符串作为两个字符导入 - 你知道为什么要添加空格吗?另外,使用grepl 而不是%in% 会被认为是更好的做法吗?
  • 我用了read.csv,现在你提了,我没有设置strip.white = TRUE。我今天学到了一些东西,谢谢!
  • 然而,当我 设置 strip/white = TRUE 时,我仍然会得到 ID 值中的空格。奇数。
  • 道歉,strip.white。第二条评论有错字,我无法编辑。
  • 一个非常完整而简洁的答案。非常感谢!
猜你喜欢
  • 2018-02-26
  • 1970-01-01
  • 1970-01-01
  • 2018-01-19
  • 1970-01-01
  • 2017-04-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多