2013-10-19 49 views
3

我有以下的數據幀(數據),從該我會想提取和打印列標題過的位置有一個非零元素:提取列標題

M1 M2 M3 M4 
2 0 1 0 1 
5 1 -1 0 0 
7 0 1 1 0 

需要的輸出:

2: M2 M4 
5: M1 M2 
7: M2 M3 

到目前爲止,我的R代碼裏面是不工作:

colnames(data)[which(data[2] !=0),] 

幫助將不勝感激。由於

+2

因爲你不能保證所有行將具有相同數量的列名稱,您應該準備好將列表作爲輸出。 –

+0

'colnames(data)'是一個向量,所以我猜你應該在[]內部沒有逗號。使用'colnames(data)[which(data [2,]!= 0)] – Frank

回答

4

讓我們的不規則的結果更一般的情況:

dat <- structure(list(M1 = c(0L, 1L, 0L), M2 = c(1L, -1L, 1L), M3 = -1:1, 
M4 = c(1L, 0L, 0L)), .Names = c("M1", "M2", "M3", "M4"), 
    class = "data.frame", row.names = c("2", "5", "7")) 

> dat 
    M1 M2 M3 M4 
2 0 1 -1 1 
5 1 -1 0 0 
7 0 1 1 0 

內申請「循環」構成一個邏輯組向量。因爲R是以列爲導向的,所以第二級處理是在列上完成的。外應用「循環」從colnames提取適當項目:

apply(apply(dat,1, as.logical) , 2, function(ll) colnames(dat)[ll]) 
$`2` 
[1] "M2" "M3" "M4" 

$`5` 
[1] "M1" "M2" 

$`7` 
[1] "M2" "M3" 

也可能已經提取出的陣列指示器版本(),然後處理結果:

> which(dat != 0, arr.ind=TRUE) 
    row col 
5 2 1 
2 1 2 
5 2 2 
7 3 2 
2 1 3 
7 3 3 
2 1 4 
+0

謝謝DWin。代碼(apply(apply(dat,1,as.logical),2,function(ll)colnames(dat)[ll]))工作出色!請稍微解釋一下代碼。 – user27976

+0

當你看R代碼時,試着找到最內層的表達式,然後從那裏「向外思考」。內部函數根據行值返回邏輯結果,然後將其作爲邏輯向量從數據幀的列名中進行選擇。由於它是作爲一組邏輯列返回的,所以邊距需要爲「2」,而不是您所期望的。 –

+0

非常感謝迪文! – user27976

1

我在添加1第一行治療不規則的情況下

mm <- read.table(text='M1 M2 M3 M4 
2 0 1 1 1 
5 1 -1 0 0 
7 0 1 1 0',header=TRUE) 


res <- apply(mm != 0,1,function(x)colnames(mm)[x]) 

$`2` 
[1] "M2" "M3" "M4" 

$`5` 
[1] "M1" "M2" 

$`7` 
[1] "M2" "M3" 

編輯是一致的,並返回一個列表:

res <- apply(mm != 0,1,function(x)colnames(mm)[x])  
if (!is.null(dim(res)) split(res,seq_along(res[,1])) 
+1

我認爲你和迪文的答案都有問題,他們會根據輸入返回一個列表或矩陣。爲了保持一致,它應該總是返回一個列表。 – flodel

+0

@ flodel很好的捕捉。我更新我的答案。 – agstudy

+0

感謝agstudy。更新是在上一行之後運行的嗎?我跑了,我得到了:「錯誤:意外的符號在」如果(!is.null(dim(res))split「」 – user27976

5

這將始終返回一個列表:

Map(`[`, list(names(df)), split(col(df)[df != 0], 
           row(df)[df != 0])) 

# [[1]] 
# [1] "M2" "M4" 
# 
# [[2]] 
# [1] "M1" "M2" 
# 
# [[3]] 
# [1] "M2" "M3" 

(你可以在裏面setNames(..., rownames(df))包裝中,如果你想要列表分享df的行名。)

+0

當然+ 1 ....!elegant! – agstudy

+0

我很感謝你的幫助flodel。請解釋map()是如何在這個上下文中使用的,謝謝 – user27976

+0

如果你熟悉函數,Map'就像'mapply'一樣,除了它總是返回一個名單。這裏的語法是'Map(f,a,b)',其中'a'和'b'是列表(你可以把它們想象成矢量)。 'Map'將遍歷這兩個列表並運行'f(a [[i]],b [[i]])''。請注意,'a'的長度爲1,所以它會被回收,所以它實際上對所有'i'運行'f(a [[1]],b [[i]])。現在,如果你用上面的這些代替'f','a','b',那應該是有道理的。 – flodel