2014-07-27 60 views
0

我在R中具有以下數據幀。它代表爲便於解釋而組成的蛋白質結構。如何在獲取某些列的最小值和最大值的同時摺疊R中的矩陣

Uniprots Chain resSeq Serial 
P68871 D 23 3446 
P68871 D 24 3453 
P68871 D 25 3457 
P68871 D 26 3461 
P68871 D 27 3470 
P69011 A 38 3561 
P69011 A 39 3568 
P69011 A 40 3577 
P69011 A 41 3588 
P69011 A 42 3599 
P69011 A 43 3610 
P69011 A 44 3619 
P69011 A 45 3625 
P69011 A 46 3636 
P0116 B 2 4239 
P0116 B 4 4242 
P0116 B 5 4268 
P0116 B 6 4279 
P0116 B 7 4285 
P0116 B 8 4299 
P0116 B 9 5015 
P0116 C 15 5055 
P0116 C 30 5199 
P0116 C 42 5239 

我要的是坍塌下來,所以它看起來是這樣的:

Uniprot Chain resSeq_start resSeq_end Serial_start Serial_end 
P68871 D  23   27   3446  3470 
P69011 A  38   46   3561  3636 
P0116 B  2    9   4239  5015 
P0116 C  15   42   5055  5239 

基本上,我要崩潰了下來在第一1,2和3列。然後我可以使用第四列作爲檢查工作。我認爲我可以用聚合做到這一點,但似乎並不奏效。我可以肯定地做一些亂七八糟的循環(繼續追加到一個新的uniprot /鏈向量),但這是醜陋的。

有一點要注意的是,Uniprot/Chain組合並不總是唯一的。具體來說,一個uniprot可以有多個鏈(如我的例子)。

謝謝你的幫助!

+0

應該是min(x $ resSeq)還是類似的? – user1357015

回答

3

aggregate:鹼溶液(我寧願)由@ user20650提供(do.call是重要的,因爲聚集體將返回的數據幀,但與矩陣元素)

do.call(data.frame, aggregate(cbind(resSeq, Serial) ~ Uniprots + Chain, 
           data = dat, function(x) c(start = min(x), end = max(x)))) 

# Uniprots Chain resSeq.start resSeq.end Serial.start Serial.end 
# 1 P69011  A   38   46   3561  3636 
# 2 P0116  B   2   9   4239  5015 
# 3 P0116  C   15   42   5055  5239 
# 4 P68871  D   23   27   3446  3470 

plyr

dat <- psych::read.clipboard() 

library(plyr) 

ddply(dat, .(Uniprots, Chain), summarise, 
     resSeq_start = min(resSeq), 
     resSeq_end = max(resSeq), 
     Serial_start = Serial[which.min(resSeq)], 
     Serial_end = Serial[which.max(resSeq)]) 

# Uniprots Chain resSeq_start resSeq_end Serial_start Serial_end 
# 1 P0116  B   2   9   4239  5015 
# 2 P0116  C   15   42   5055  5239 
# 3 P68871  D   23   27   3446  3470 
# 4 P69011  A   38   46   3561  3636 

(可能不需要which.min/max)

+0

do.call(data.frame ...)部分的用途是什麼? – user1357015

+0

簡短的回答:它強制看起來像一個正常的data.frame(它不是)到一個正常的data.frame。查看帶有和不帶'do.call'的'str'。 – rawr

+0

cbind在公式的左邊創建一個矩陣,然後aggregate.formula返回一個數據框。但是由於數據框只是一個列表的集合(持有它們的結構),用cbind創建的矩陣仍然存在。 do.call(data.frame ...將矩陣強制轉換爲data.frame,以便您可以使用運算符('$',''')或其他任何屬於(您期望是常規數據框的內容)結果。 – rawr

3

我會推薦data.table。

下面是一個簡單的實現:

第一步:將data.frame到data.table:

​​

第二步:創建新列:

dt[, `:=`(resSeq_start = min(resSeq), 
      resSeq_end = max(resSeq), 
      Serial_start = min(Serial), 
      Serial_end = max(Serial)), 
by = list(Uniprots, Chain)] 

第三步:取下舊列:

res <- dt[, c("Serial", "resSeq") := NULL] 

第四步:只保留唯一列:

unique(res, by=c("Uniprots", "Chain")) 
# Uniprots Chain resSeq_start resSeq_end Serial_start Serial_end 
# 1: P68871  D   23   27   3446  3470 
# 2: P69011  A   38   46   3561  3636 
# 3: P0116  B   2   9   4239  5015 
# 4: P0116  C   15   42   5055  5239 

我已經說明兩種方式來添加/使用data.table這裏引用刪除列。一個使用c("col", "col2") := list(val1, val2),另一個使用`:=`(col1 = val1,col2 = val2)。

希望這會有所幫助。你應該閱讀更多關於data.table。

+0

@阿倫:感謝您使用新功能編輯!只是想知道如何與data.table的最新進展保持聯繫,並且可能有所貢獻。 – Shambho

+0

Shambho,當然:)。這些功能並非真正的新功能。然而'data.table'正在迅速發展。保持最新的最佳方式是1)訂閱郵件列表,2)在[github](https://github.com/Rdatatable/data.table)上關注項目標籤。如果你有貢獻,這將會很棒!首先,我想拉請求...馬特和/或我會很樂意幫助你解決任何問題。您可以從data.table郵件列表中輕鬆找到我們的電子郵件。 – Arun

+0

謝謝Arun!只是一個免責聲明,我對版本控制(和github)非常新穎。這需要一些提升,但爲它而起。我在哪裏可以找到郵件列表? – Shambho

4

而且當然還有dplyr

require(dplyr) 
dat %>% group_by(Uniprots, Chain) %>% 
    summarize(resSeq_start = min(resSeq), 
       resSeq_end = max(resSeq), 
       Serial_start = min(Serial), 
       Serial_end = max(Serial)) 
相關問題