2016-09-20 116 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