【问题标题】:Impact of NA's when filtering Data Frames过滤数据帧时 NA 的影响
【发布时间】:2017-11-20 17:15:42
【问题描述】:

我有一个大数据框,其中包括以下 2 个字段和显示的行数(为简单起见仅显示 2 列):

> nrow(df)
[1] 3541393

> summary(df$ttlVisits)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  1.000   1.000   1.000   1.527   1.000 118.000 
> summary(df$AVGsessTOS)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's 
  1      27      30     115      72   21554  280146 

我想删除 AVGsessTOS > 1628 的行

> nrow(df[df$AVGsessTOS>=1628,])
[1] 300645

所以,我运行以下命令,预计要删除 300,645 行,但结果却是 20,499:

过滤器 1:

df

命令对行数和原始 2 列的影响:

> 3541393 - nrow(df)
[1] 20499

> summary(df$ttlVisits)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's 
   1.00    1.00    1.00    1.53    1.00  118.00  280146 
> summary(df$AVGsessTOS)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's 
    1.0    27.0    30.0   102.5    70.0  1627.5  280146 

如果我对过滤方法进行简单更改并使用 'which' 函数,我会得到预期的结果。

过滤器 2:

df df

以及命令的影响:

> 3541393 - nrow(df)
[1] 300645

> summary(df$ttlVisits)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  1.000   1.000   1.000   1.526   1.000 118.000 
> summary(df$AVGsessTOS)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
    1.0    27.0    30.0   102.5    70.0  1627.5 

我对上述内容的解释是,过滤器 #1 导致预期的 300,645 行被删除,但由于 df$AVGsessTOS 中存在 NA,因此产生了添加 280,146 个“空行”的副作用。 (300,645 - 280,146 = 20,499)

有人可以证实我对这些结果的解释,这是过滤器 #1 的预期行为吗?

也许这也可以帮助其他人避免被此所困扰。谢谢

更新:用 mtcars 复制问题:

 data(mtcars) 
 set.seed(66)

> nrow(mtcars)
[1] 32

看'carb'列的分布明细和预期的一样,一共32个:

 > table(mtcars$carb)
 1  2  3  4  6  8 
 7 10  3 10  1  1 

现在将 3 carb 值设置为 NA(不是整行,只是 carb 值)以创建与我的数据集相似的数据,以说明问题:

 set.seed(66)
 mtcars[sample(1:nrow(mtcars), 3), ]$carb <- NA

再次,'carb' 列的分布总计 29 与预期一致,在设置 NA 后比原来的少 3:

> table(mtcars$carb)
 1  2  3  4  6  8 
 6 10  1 10  1  1 

现在,删除上面显示的 6 行,碳水化合物值为 1

> mtcars2 <- mtcars[mtcars$carb>=2,]

确认预期的记录已被删除:

> table(mtcars2$carb)
 2  3  4  6  8 
10  1 10  1  1 

但是,行数与上述计数不一致:

> nrow(mtcars2)
26

检查数据显示 3 整行 NA 值。 这些行来自哪里?

View(mtcars2)
( replicate to see output of 'view' )

【问题讨论】:

    标签: r dataframe filter


    【解决方案1】:

    我对上面的解释是过滤器 #1 导致了预期的 删除 300,645 行,但副作用是增加了 280,146 “空行”是由于 df$AVGsessTOS 中存在 NA。 ( 300,645 - 280,146 = 20,499)

    原则上,子集不能扩展您的数据框。看看下面的例子:

    对于数据集:

    set.seed(123)
    mtcars[sample(1:10, 3), ] <- NA
    

    根据条件mtcars[mtcars$carb &gt; 2, ]过滤值将得到匹配行和NAs

    >> mtcars[mtcars$carb > 2, ]
                         mpg cyl  disp  hp drat    wt  qsec vs am gear carb
    Mazda RX4           21.0   6 160.0 110 3.90 2.620 16.46  0  1    4    4
    Mazda RX4 Wag       21.0   6 160.0 110 3.90 2.875 17.02  0  1    4    4
    NA                    NA  NA    NA  NA   NA    NA    NA NA NA   NA   NA
    NA.1                  NA  NA    NA  NA   NA    NA    NA NA NA   NA   NA
    Duster 360          14.3   8 360.0 245 3.21 3.570 15.84  0  0    3    4
    NA.2                  NA  NA    NA  NA   NA    NA    NA NA NA   NA   NA
    Merc 280            19.2   6 167.6 123 3.92 3.440 18.30  1  0    4    4
    Merc 280C           17.8   6 167.6 123 3.92 3.440 18.90  1  0    4    4
    Merc 450SE          16.4   8 275.8 180 3.07 4.070 17.40  0  0    3    3
    

    fortunes 包提供了更有趣的解释:

    fortunes::fortune(which = "is.na")
    

    JPM Miao:为什么 R 不能理解 if(num!=NA)?

    Peter Dalgaard:因为与未知值比较会产生未知结果。

    David Winsemius:其他任何事情都会违反热力学第二定律。我们不能进行减少熵的比较,现在可以吗?不确定性不能上坡。

    JPM Miao、Peter Dalgaard 和 David Winsemius(关于为什么需要 is.na())R-help(2013 年 5 月)

    哪个

    至于whichwhichaims to return index of elements where logical value is TRUE所扮演的角色,如果对比结果:

    >> which(mtcars$carb > 2)
     [1]  2  7 11 12 13 14 15 16 17 24 29 30 31
    >> mtcars$carb > 2
     [1]    NA  TRUE    NA    NA FALSE FALSE  TRUE    NA    NA    NA  TRUE  TRUE  TRUE
    [14]  TRUE  TRUE  TRUE  TRUE FALSE FALSE FALSE FALSE FALSE FALSE  TRUE FALSE FALSE
    [27] FALSE FALSE  TRUE  TRUE  TRUE FALSE
    

    which 返回条件为真的行索引,而子集操作返回三个值 NATRUEFALSE

    【讨论】:

    • 宾果游戏。是的,你是对的。问题出在我最初预期的 300,645 中。 nrow(df[df$AVGsessTOS>=1628,]) 基本上也计算了 280,146 个 NA。
    • 康拉德,我将暂时撤回对答案的接受,因为我刚刚注意到一个未解决的问题。虽然我理解并同意您关于“原则上,子集化无法扩展您的数据”的观点,但我们如何解释添加到 df$ttlVisits 的 280,146 个 NA? (参见过滤器#1)。我使用 mtcars 数据复制了相同的问题并将其添加到上面。如果您在最后一步查看数据,您将看到原始数据中没有的 NA 行。
    【解决方案2】:

    看起来是的?我一般不这样过滤,一般我用dplyr

    set.seed(123)
    df <- data.frame(x = sample(1:5, 100, replace = TRUE), y = sample(c(1, 4, NA), 100, replace = TRUE))
    

    不使用哪个:

    > head(df[(df$y < 2),], 10)
          x  y
    2     4  1
    NA   NA NA
    NA.1 NA NA
    NA.2 NA NA
    10    3  1
    NA.3 NA NA
    12    3  1
    13    4  1
    NA.4 NA NA
    NA.5 NA NA
    

    使用哪个:

    > head(df[which(df$y < 2),], 10)
       x y
    2  4 1
    10 3 1
    12 3 1
    13 4 1
    16 5 1
    22 4 1
    23 4 1
    24 5 1
    27 3 1
    28 3 1
    

    我鼓励您使用 head()View()(在 RStudio 中)或以某种方式打印它们来调查您的数据框。它将有助于回答其中一些关于想知道发生了什么的问题!

    【讨论】:

    • Matt,在这个特定的数据集 head() 和 view() 的情况下,两个过滤器的结果完全相同。 (或原始数据集)。
    • 真的吗?!那很有趣。我想知道为什么会这样。
    猜你喜欢
    • 2017-04-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-21
    • 2022-11-30
    • 2017-03-16
    • 2021-04-10
    • 2018-02-20
    相关资源
    最近更新 更多