【问题标题】:Strange behaviour dropping column from data.frame in R从 R 中的 data.frame 中删除列的奇怪行为
【发布时间】:2017-01-24 14:48:53
【问题描述】:

从 data.frame 中删除列时,我遇到了一个奇怪的行为。最初我有:

> a <- data.frame("a" = c(1,2,3), "abc" = c(3,2,1)); print(a)
  a abc
1 1   3
2 2   2
3 3   1

现在,我从 data.frame 中删除 a$a

> a$a <- NULL; print(a)
  abc
1   3
2   2
3   1

正如预期的那样,我的 data.frame 中只有 abc 列。但是奇怪的部分开始了,当我尝试引用已删除的列a

> print(a$a)
[1] 3 2 1
> print(is.null(a$a))
[1] FALSE

看起来 R 返回的值是 a$abc 而不是 NULL

当剩余列的名称的开头与已删除列的名称完全匹配时会发生这种情况。

这是一个错误还是我在这里遗漏了什么?

【问题讨论】:

  • 你是正确的@Chase,虽然问题的标题不是最好的搜索。
  • @lselzer - 我当然同意。我只知道它存在,因为我回答了它。 JD修复了这个问题,我会相应地更新另一个问题。或者他们应该被合并......或者什么。
  • 这只是 R 试图变得聪明并猜测你的意思。它认为a$a 表示a$abc,因为这是唯一可能的选择。这不适用于a &lt;- data.frame("a" = c(1,2,3), "b" = c(3,2,1)); a$a &lt;- NULL ; is.null(a$a)。在这种情况下,它只是偶然起作用,因为两列都以 a 开头。
  • 正如help("$") 解释的那样,$ 进行部分匹配。

标签: r dataframe


【解决方案1】:

来自帮助。 ?$

name:文字字符串或 名称(可能是反引号)。为了 提取,这通常是(见 在“环境”下)部分 与对象的名称相匹配。

这是正常行为,因为名称部分匹配。有关部分匹配的更多信息,请参阅 ?pmatch。

干杯

【讨论】:

    【解决方案2】:

    也许值得指出(因为它没有出现在之前的 related question 中)这种部分匹配行为可能是避免使用 '$' 的一个原因,除非在交互式使用 R 时作为一种方便的简写方式(至少,这是小心使用它的原因)。

    如果您知道列的名称但不知道位置,则通过dat[,'ind'] 选择列,或者如果您知道位置,则通过dat[,3] 选择列通常更安全,因为您不会与部分匹配发生冲突。

    【讨论】:

      【解决方案3】:

      虽然您的确切问题已在 cmets 中得到解答,但避免此行为的另一种方法是将您的 data.frame 转换为 tibble,这是 data.frame 的精简版,没有 列名 munging,其中other things:

      library(tibble)
      df_t <- as_data_frame(a)
      df_t
      # A tibble: 3 × 1
          abc
        <dbl>
      1     3
      2     2
      3     1
      > df_t$a
      NULL
      Warning message:
      Unknown column 'a' 
      

      【讨论】:

      • 这是我正在寻找的东西。不幸的是,它比较慢。根据我的测量(不广泛),慢了 3 倍。
      【解决方案4】:

      来自 R 语言定义 [第 3.4.1 节 pg.16-17] --

      https://cran.r-project.org/doc/manuals/r-release/R-lang.pdf

      字符:i 中的字符串与x 的names 属性匹配,并使用生成的整数。对于 [[ 和 $,如果精确匹配失败,则使用部分匹配,因此如果 x 不包含名为“aa”的组件并且“aabb”是唯一具有前缀“aa”的名称,则 x$aa 将匹配 x$aabb。对于 [[,部分匹配可以通过默认为 NA 的确切参数来控制,表示允许部分匹配,但应该导致 发生时发出警告。将精确设置为 TRUE 可防止发生部分匹配,FALSE 值允许它并且不会发出任何警告。请注意, [ 始终需要完全匹配。字符串 "" 被特殊对待:它表示‘没有名字’并且不匹配任何元素(甚至不匹配那些没有名字的元素)。请注意,部分匹配仅在提取时使用 而不是在更换时。

      【讨论】:

        猜你喜欢
        • 2019-10-29
        • 2011-09-11
        • 1970-01-01
        • 2014-10-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多