2016-09-20 117 views
0

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

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的每一行中具有相同数目的NAs。我似乎无法得到正确的代码来做到这一点。建议感激!

+0

所有的行都会有2列不是“NA”吗? – davechilders

+0

是的。好问题。意味着把这个问题放在这个问题上。是的,最终矩阵中将有N列,例如N = 2,并且每行中的NAs数量相同。 – Ernie

回答

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 
+0

这当然有用,但把我带入了tidyr和dplyr的工具箱,我还没有完全熟悉。谢谢。 – Ernie

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))) 

这里最棘手的部分是你的目标真正改变数据帧结构,所以“删除NA每一行”的任务必须由行作为新的数据帧建行,因为每行每列可来了来自原始数据框的不同列。我们可以使用na.omit,然后转置回行。

我用了2个for循环,但for循环在R中不一定是坏的。第一个对每列都是向量化的。无论如何,第二个需要逐行进行。

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

+0

这是一个非常糟糕的做法。你在同时增长对象的同时一个接一个地运行两个for循环。这与R –

+0

中的所有基本编程规则无关我不确定我是否按照答案new_dt进行操作,该例子是列值为1,2,3和3,2,6的3X2 df。目前尚不清楚这是如何给出我想要的答案,即4×2矩阵或df。 – Ernie

+0

越来越多的对象是坏的,我可以先创建一个固定大小的列表,然后将它们组合在一起。但是,这将需要'data.table'和OP不需要额外的软件包。我不确定是否有其他方法绑定数据帧行而不增加对象。 – dracodoc

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

+0

David,非常好,这是一个紧凑的解决方案,可以避免plyr和tidyr,两者都很有用,但需要一些熟练使用的研究。 – Ernie