我有一个数据框,最终将其转换为xts
对象。第一列包含日期数据,而所有其他列均包含数字数据。但是,并非所有数字列都具有相同数量的值/相同的长度。某些列比其他列包含更多的行。
我想通过删除具有最少数量的NA的列中包含NA的行来过滤我的数据帧,但对于我选择的所有其他列,仍然保留包含NA的行。例如,下面的grpA列具有最少数量的NA。我想删除包含NA的数据帧的前2行,但无论它们是什么,都保留grpB中的值。
我所拥有的:
Date grpA grpB
2007-11-06 NA NA
2007-11-07 NA NA
2007-11-09 1.66 NA
2007-11-12 1.64 NA
2007-11-13 1.61 1.28
2007-11-14 1.60 1.30
2007-11-15 1.57 1.27
2007-11-16 1.56 1.25
2007-11-19 1.55 1.25
2007-11-20 1.55 1.25
2007-11-21 1.52 1.22
2007-11-22 1.50 1.21
2007-11-23 1.51 1.21
2007-11-26 1.52 1.25
2007-11-27 1.50 1.25
2007-11-28 1.50 1.23
2007-11-29 1.52 1.24
2007-11-30 1.56 1.25
2007-12-03 1.56 1.22
2007-12-04 1.56 1.23
我想要什么:
Date grpA grpB
2007-11-09 1.66 NA
2007-11-12 1.64 NA
2007-11-13 1.61 1.28
2007-11-14 1.60 1.30
2007-11-15 1.57 1.27
2007-11-16 1.56 1.25
2007-11-19 1.55 1.25
2007-11-20 1.55 1.25
2007-11-21 1.52 1.22
2007-11-22 1.50 1.21
2007-11-23 1.51 1.21
2007-11-26 1.52 1.25
2007-11-27 1.50 1.25
2007-11-28 1.50 1.23
2007-11-29 1.52 1.24
2007-11-30 1.56 1.25
2007-12-03 1.56 1.22
2007-12-04 1.56 1.23
数据帧的可重现示例如下:
df <- data.frame(Date = structure(c(1194307200, 1194393600, 1194566400,
1194825600, 1194912000, 1194998400, 1195084800, 1195171200, 1195430400,
1195516800, 1195603200, 1195689600, 1195776000, 1196035200, 1196121600,
1196208000, 1196294400, 1196380800, 1196640000, 1196726400), class = c("POSIXct",
"POSIXt"), tzone = "UTC"),
grpA = c(NA, NA, 1.66, 1.64, 1.61, 1.6, 1.57, 1.56, 1.55, 1.55, 1.52, 1.5, 1.51, 1.52, 1.5, 1.5, 1.52, 1.56, 1.56, 1.56),
grpB = c(NA, NA, NA, NA, 1.28, 1.3, 1.27, 1.25, 1.25, 1.25, 1.22, 1.21, 1.21, 1.25, 1.25, 1.23, 1.24, 1.25, 1.22, 1.23))
我已经尝试过drop_na
包中的tidyr
函数,并且可以正常工作:
df2 <- drop_na(df, grpA)
但是,我将在Shiny App中使用上述过滤器,并且我事先不知道用户会选择哪些列中包含NA的行数最少。
我已经尝试了以下方法来确定其中包含NA的行数最少的列,但是它为我提供了非NA行的数目,而不是列名:
max(colSums(!is.na(df[-1])))
我尝试使用以下方法提取列的名称,但遇到错误:
colnames(df)[which(colSums(!is.na(df[-1]))) == max(colSums(!is.na(df[-1])))]
我认为这是一项简单的任务,但它变得相当复杂。我需要能够在闪亮的反应式表达中使用答案。
非常感谢!
答案 0 :(得分:4)
我们首先可以找到数量最少为NA
的列名称,然后从该列中删除NA
行。
col <- names(which.min(colSums(is.na(df[-1]))))
df[!is.na(df[col]), ]
# Date grpA grpB
#3 2007-11-09 1.66 NA
#4 2007-11-12 1.64 NA
#5 2007-11-13 1.61 1.28
#6 2007-11-14 1.60 1.30
#7 2007-11-15 1.57 1.27
#8 2007-11-16 1.56 1.25
#9 2007-11-19 1.55 1.25
#10 2007-11-20 1.55 1.25
#11 2007-11-21 1.52 1.22
#12 2007-11-22 1.50 1.21
#13 2007-11-23 1.51 1.21
#14 2007-11-26 1.52 1.25
#15 2007-11-27 1.50 1.25
#16 2007-11-28 1.50 1.23
#17 2007-11-29 1.52 1.24
#18 2007-11-30 1.56 1.25
#19 2007-12-03 1.56 1.22
#20 2007-12-04 1.56 1.23
也可以单行完成,而无需创建其他变量
df[!is.na(df[names(which.min(colSums(is.na(df[-1]))))]), ]
使用相同的逻辑,dplyr
方法可能会使用filter_at
library(dplyr)
df %>%
filter_at(df %>%
summarise_at(-1, ~sum(is.na(.))) %>%
which.min %>% names, ~!is.na(.))
或与tidyr::drop_na
tidyr::drop_na(df, df %>%
summarise_at(-1, ~sum(is.na(.))) %>%
which.min %>% names)