【问题标题】:How to filter or subset data in R per row如何在 R 中每行过滤或子集数据
【发布时间】:2020-03-09 12:04:21
【问题描述】:

我对 R 比较陌生,但仍在研究如何从数据框中过滤数据。我有一个由 406 行和 48 列组成的数据框,其中缺少一些数据:

set.seed(123)
mydata <- data.frame(matrix(rnorm(406*48), nrow = 406, ncol = 48))
diag(mydata) <- NA
mydata[10:20,25:40] <- NA

我现在要做的是遍历每一行并选择所有

newdata <- c()
#go through each row
for (j in 1:nrow(mydata)){
#within each row look at all the entries, store all entries that are <= 0 in a new variable, rowwise
  for (i in 1:ncol(mydata)){
    newdata[] <- mydata[j,i][mydata[j,i]<= 0]
}
}

作为newdata 的最终结果,我希望有一个包含 406 行的变量,其中在每一行中,我有mydata 的相应行的所有条目NA,所以newdata 中的每一行可以有不同数量的条目。

有人可以帮忙吗?

【问题讨论】:

  • 那么在您删除数据的地方(即值 > 0),您打算拥有什么? NA?
  • 我只想删除这些值。
  • 但是矩阵的布局会是什么样子呢?您可能有一排保留 10 个值,而另一排保留 8 个值——剩下的 2 个空格中会是什么?维度需要保持一致,除非您正在考虑除矩阵或数据框之外的其他结构
  • 那么在值>0的情况下,我也想拥有NA
  • @Friederike,在下面的回答中,我为您提供了两种摆脱正值并将其替换为 NA 的方法。

标签: r dataframe filter row subset


【解决方案1】:

编辑:替代解决方案(一行)

或者(根据您的 cmets),您可以在一行中用 NA 替换正值:

mydata = apply(mydata,2,function(x){x = ifelse(x <= 0,x,NA)})

这是mydata之前第一行的输出:

> as.numeric(mydata[1,])
 [1]          NA -0.34975424 -0.07767320 -1.16193756 -0.33768064 -1.09321744  0.66392711  0.27303842 -2.23650827
[10] -0.42412913  1.44870575  0.03134468  0.19868021  0.17935206  1.51321052 -0.33100059  0.26331289 -0.20527804
[19] -0.22355074 -0.96041834 -0.82061841  0.67362771 -1.11751900 -0.58768884 -1.14399798  0.11782292 -1.51231253
[28] -1.93607886 -0.33478355  0.70214667  0.51443110 -1.04816477 -1.20696026 -0.97035477 -0.40159316  0.80351157
[37]  1.07208956  0.08778464  0.40148417  1.27912058 -0.90539292 -2.57307640 -0.38050016 -0.51386913  0.39852024
[46]  0.68074424 -0.04131547 -1.58519483

之后:

> as.numeric(mydata[1,])
 [1]          NA -0.34975424 -0.07767320 -1.16193756 -0.33768064 -1.09321744          NA          NA -2.23650827
[10] -0.42412913          NA          NA          NA          NA          NA -0.33100059          NA -0.20527804
[19] -0.22355074 -0.96041834 -0.82061841          NA -1.11751900 -0.58768884 -1.14399798          NA -1.51231253
[28] -1.93607886 -0.33478355          NA          NA -1.04816477 -1.20696026 -0.97035477 -0.40159316          NA
[37]          NA          NA          NA          NA -0.90539292 -2.57307640 -0.38050016 -0.51386913          NA
[46]          NA -0.04131547 -1.58519483

以前的解决方案

这是另一种解决方案,可能不是最好的,但看起来应该没问题。 使用您描述的数据框:

set.seed(123)
mydata <- data.frame(matrix(rnorm(406*48), nrow = 406, ncol = 48))
diag(mydata) <- NA
mydata[10:20,25:40] <- NA

我们基本上会创建一个列表来存储每一行​​的所有负值

list_data = vector("list",nrow(mydata))
for(i in 1:nrow(mydata))
{
  list_data[[i]] = mydata[i,which(mydata[i,]<=0)]
}

然后,为了将列表转换为数据框,我们用 NA 值填充每个缺失值,以便每行具有完全相同数量的值

maxlength = max(sapply(list_data,length))
List_Data = lapply(list_data, function(x){c(x,rep(NA,maxlength-length(x)))})
List_Data = do.call(rbind,List_Data)
List_Data = data.frame(List_Data)

这里是第一列的输出:

> head(List_Data)
          X1         X2          X3          X4         X5         X6         X7          X8         X9
1         NA -0.3497542 -0.07767320 -1.16193756 -0.3376806 -1.0932174 -2.2365083 -0.42412913 -0.3310006
2 -0.2301775         NA -1.58908969 -0.03795763 -0.4079667 -0.2509906 -0.5778989 -0.14031375 -1.5660913
3 -0.5388092         NA -1.16618981 -0.22729115 -0.5017032 -1.0556810 -1.0237632 -0.89231744 -2.0031559
4         NA -1.0387278 -0.07765504 -0.15323396 -0.8953830 -1.3724905 -0.5035273 -0.05266103 -1.0722186
5 -0.1941524 -2.1645471          NA -0.90793470 -0.7849893 -0.8245955 -0.3935175 -0.18426891 -0.0757480
6 -0.6375688         NA -0.13461283 -1.03171727 -1.1625653 -0.7045958 -0.5746850 -0.19752782 -0.3510071

正如我所说,可能有最快、更优雅的方法来实现相同的结果,但这种解决方案有效。

【讨论】:

    【解决方案2】:

    如果您的目标是简单地将正值替换为 NA,则可以是 非常简单地利用了 R 的矢量化。

    首先让我制作一个较小的示例数据集,以便我们可以查看所有内容:

    set.seed(1)
    nrow <- 6
    ncol <- 4
    mydata <- data.frame(matrix(rnorm(nrow * ncol), nrow = nrow, ncol = ncol))
    diag(mydata) <- NA
    mydata[4:5, 1:2] <- NA
    mydata
    
    ##           X1        X2          X3          X4
    ## 1         NA 0.4874291 -0.62124058  0.82122120
    ## 2  0.1836433        NA -2.21469989  0.59390132
    ## 3 -0.8356286 0.5757814          NA  0.91897737
    ## 4         NA        NA -0.04493361          NA
    ## 5         NA        NA -0.01619026  0.07456498
    ## 6 -0.8204684 0.3898432  0.94383621 -1.98935170
    

    这在更大的数据集上同样适用(事实上,通过避免 apply 或循环这种方法会更好)。

    现在就像将我们想要设置为 NA 的布尔值一样简单 (在本例中为 mydata &gt; 0),然后就这样做了!

    mydata[mydata > 0] <- NA
    mydata
    
    ##           X1 X2          X3        X4
    ## 1         NA NA -0.62124058        NA
    ## 2         NA NA -2.21469989        NA
    ## 3 -0.8356286 NA          NA        NA
    ## 4         NA NA -0.04493361        NA
    ## 5         NA NA -0.01619026        NA
    ## 6 -0.8204684 NA          NA -1.989352
    

    但从 OP 看来,您想要的更像是一个 list,其中 每个元素可以有不同的长度(注意:每个元素都有一个data.frame必须具有相同数量的条目;然而,一个列表允许每个 元素具有任意数量的条目)。

    例如,要制作这样的列表,您可以尝试以下操作:

    mylist <- lapply(1:nrow(mydata), function(i) {
        x <- mydata[i, ]
        x[x <= 0 & !is.na(x)]
    })
    mylist
    
    ## [[1]]
    ## [1] -0.6212406
    ## 
    ## [[2]]
    ## [1] -2.2147
    ## 
    ## [[3]]
    ## [1] -0.8356286
    ## 
    ## [[4]]
    ## [1] -0.04493361
    ## 
    ## [[5]]
    ## [1] -0.01619026
    ## 
    ## [[6]]
    ## [1] -0.8204684 -1.9893517
    

    再次,我们必须使用列表,因为并非所有元素都保证具有相同的长度。

    【讨论】:

    • 不错!我觉得很愚蠢,没有考虑mydata[mydata &gt; 0] &lt;- NA ;) 这绝对是最简单的方法。
    猜你喜欢
    • 2021-10-05
    • 2015-11-03
    • 2019-12-14
    • 1970-01-01
    • 2017-11-01
    • 2022-11-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多