根据数据框内容R选择列名

时间:2016-09-20 20:41:31

标签: r dataframe subset

我想通过选择数据框中包含的元素不包含NA的列的名称来构建矩阵或数据框。例如,假设我有:

zz <- data.frame(a = c(1, NA, 3, 5),
                     b = c(NA, 5, 4, NA),
                     c = c(5, 6, NA, 8))

给出:

   a  b  c
1  1 NA  5
2 NA  5  6
3  3  4 NA
4  5 NA  8

我想识别每个NA并构建一个新的矩阵或df,如下所示:

a  c
b  c
a  b
a  c

输入矩阵/ df的每一行中将有相同数量的NA。我似乎无法获得正确的代码来执行此操作。建议赞赏!

3 个答案:

答案 0 :(得分:3)

library(dplyr)
library(tidyr)

zz %>%
  mutate(k = row_number()) %>%
  gather(column, value, a, b, c) %>%
  filter(!is.na(value)) %>%
  group_by(k) %>%
  summarise(temp_var = paste(column, collapse = " ")) %>%
  separate(temp_var, into = c("var1", "var2"))

# A tibble: 4 × 3
      k  var1  var2
* <int> <chr> <chr>
1     1     a     c
2     2     b     c
3     3     a     b
4     4     a     c

答案 1 :(得分:3)

这是一种可能的矢量化基础R方法

indx <- which(!is.na(zz), arr.ind = TRUE)
matrix(names(zz)[indx[order(indx[, "row"]), "col"]], ncol = 2, byrow = TRUE)
#    [,1] [,2]
#[1,] "a"  "c" 
#[2,] "b"  "c" 
#[3,] "a"  "b" 
#[4,] "a"  "c" 

这会找到非NA索引,按行排序,然后根据排序索引对zz数据集的名称进行子集化。如果您喜欢矩阵,可以将其包装到as.data.frame

答案 2 :(得分:1)

编辑:在处理前将数据帧转置一次,因此不需要在第一版中循环转置两次。

cols <- names(zz)
for (column in cols) {
  zz[[column]] <- ifelse(is.na(zz[[column]]), NA, column)
}
t_zz <- t(zz)
cols <- vector("list", length = ncol(t_zz))
for (i in 1:ncol(t_zz)) {
  cols[[i]] <- na.omit(t_zz[, i])
}
new_dt <- as.data.frame(t(do.call("cbind", cols)))

这里棘手的部分是你的目标是实际改变数据框架结构,所以&#34;删除每一行中的NA&#34;必须逐行构建新数据框,因为每行中的每一列都可能来自原始数据框的不同列。

zz[1, ]是一行数据框,使用t将其转换为向量,以便我们可以使用na.omit,然后转置回行。

我使用2 for循环,但for循环在R中不一定是坏的。第一个是为每列进行矢量化。无论如何,第二个需要逐行完成。

编辑:在R中,增长对象的性能非常糟糕。我知道我可以使用rbindlist中的data.table来获取数据框列表,但是OP不想要新的包。我的第一次尝试只使用rbind,它不能将列表作为输入。后来我发现另一种方法是使用do.callIt's still slower than rbindlist though