【问题标题】:Removing all empty columns and rows in data.frame when rows don't go away当行不消失时删除 data.frame 中的所有空列和行
【发布时间】:2019-10-07 15:38:38
【问题描述】:

我有两个 data.frames,dA (HERE) 和 dB (HERE)。除了dB 有一个完全空的列和多个空行之外,它们完全相同。

dA <- read.csv("https://raw.githubusercontent.com/izeh/m/master/irr3.csv", h = T)
dB <- read.csv("https://raw.githubusercontent.com/izeh/m/master/irr4.csv", h = T)

我想删除dB 中的所有空列和所有空行,以便dB 变得与dA 完全相同。

目前,我尝试以下方法来实现我的目标但看起来空行没有被删除

# remove columns with all NA
B1 <- dB[, colSums(is.na(dB)) != nrow(dB)]

# remove rows with all NA
B2 <- B1[rowSums(is.na(B1)) != ncol(B1), ]   # NOW, check by:  `nrow(B2)` the `NA` haven't 
                                             # been removed !!

【问题讨论】:

  • @NelsonGon,这个问题不一样!
  • 通常最好在您的问题中包含不链接到外部站点的示例数据。该回购可能会在未来被存档/删除。 dput 是几个更好的选择之一。

标签: r function loops dataframe na


【解决方案1】:

您有 NA 和空行。你可以这样做

B1[rowSums(is.na(B1) | B1 == "") != ncol(B1), ]

#   study.name  group.name outcome ESL prof scope type
#1  Shin.Ellis    ME.short       1   1    2     1    1
#2  Shin.Ellis     ME.long       1   1    2     1    1
#3  Shin.Ellis   DCF.short       1   1    2     1    2
#4  Shin.Ellis    DCF.long       1   1    2     1    2
#5  Shin.Ellis  Cont.short       1   1    2    NA   NA
#6  Shin.Ellis   Cont.long       1   1    2    NA   NA
#8    Trus.Hsu       Exper       1   2    2     2    1
#.....

我们也可以从dplyr使用filter_all

library(dplyr)
B1 %>% filter_all(any_vars(!is.na(.) & . != ""))

【讨论】:

  • 您可以在read.csv 中指定na.strings,并包含您想要转换为NA 的所有内容。例如,这对你有用dB &lt;- read.csv("https://raw.githubusercontent.com/izeh/m/master/irr4.csv", h = T, na.strings = c("NA", ""))
  • Ronak,setNames(x, sub("\\.\\d+$", "", names(x)))setNames(x, sub("\\.\\d+", "", names(x))) 有什么区别?有一个额外的$ 标志?
  • @Reza $ 表示字符串的结尾。因此,在第一种情况下,.number 如果出现在字符串末尾,则将被删除,而在第二种情况下,它将从字符串中的任何位置删除。
【解决方案2】:

这是Filter 来自base R 的选项

Filter(function(x) !all(is.na(x)), dB)
#  study.name  group.name outcome ESL prof scope type
#1  Shin.Ellis    ME.short       1   1    2     1    1
#2  Shin.Ellis     ME.long       1   1    2     1    1
#3  Shin.Ellis   DCF.short       1   1    2     1    2
#4  Shin.Ellis    DCF.long       1   1    2     1    2
#5  Shin.Ellis  Cont.short       1   1    2    NA   NA
#6  Shin.Ellis   Cont.long       1   1    2    NA   NA
#7                              NA  NA   NA    NA   NA
#8    Trus.Hsu       Exper       1   2    2     2    1
#...

或者any

Filter(function(x) any(!is.na(x)), dB)

删除行

B1[!!rowSums(!is.na(B1) & B1 != ""),] 

或使用Reduce

B1[Reduce(`|`, lapply(B1, function(x) !is.na(x) & x != "" )),]

【讨论】:

  • 阿伦,setNames(x, sub("\\.\\d+$", "", names(x)))setNames(x, sub("\\.\\d+", "", names(x))) 有什么区别?有一个额外的$ 标志?
  • @Reza 这是基于同一篇文章。差异是基于一个错字。两者都应该是$。如果只有一个 .\\d+ 实例,那么两者都可以工作。但否则,可以给出不同的结果。这里$是为了确保它是字符串的结尾
  • @Reza 我更新了我的评论。这基本上是一个错字,但应该适用于只有一个 . 实例后跟一个或多个数字的情况
  • 关于那篇文章的另一件事,x[setdiff(names(x), ar)]x[ , !names(x) %in% ar] 之间有什么区别,其中x 是一个 data.frame,ar 是一个名称字符向量?
  • @Reza 前者仅返回 unique 名称。如果您有重复,它将被删除,而后者会给出一个完整长度的逻辑输出 (TRUE/FALSE),并且使用它您的重复名称不会被删除
【解决方案3】:

您可以使用replace"" 转换为NA,然后使用is.na。要删除完整的行和列,您可以使用 apply 和函数 all

x  <- is.na(replace(dB, dB=="", NA))
dB[!apply(x, 1, all), !apply(x, 2, all)]

或使用rowSumscolSums,就像问题中一样:

x <- is.na(dB) | dB == ""
dB[rowSums(x) != ncol(x), colSums(x) != nrow(x)]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-11-03
    • 1970-01-01
    • 1970-01-01
    • 2011-05-06
    • 2017-07-31
    • 1970-01-01
    • 2013-06-22
    • 1970-01-01
    相关资源
    最近更新 更多