2015-10-23 66 views
3

我需要使用另一個矩陣作爲標識符(ID.MA)來填充來自長數據幀(DF)的信息的矩陣(MA)。將數據框與data.table匹配

我的三個矩陣的一個想法: MA.ID創建一個標識符來看看在大DF所需的變量:

 a  b  c 
a ID.aa ID.ab ID.ac 
b ID.ba ID.bb ID.bc 
c ID.ca ID.cb ID.cc 

原來的大數據幀無用的信息,但也已經是行對我有用填充目標MA矩陣:

ID  1990 1991 1992 
ID.aa 10 11 12 
ID.ab 13 14 15 
ID.ac 16 17 18 
ID.ba 19 20 21 
ID.bb 22 23 24 
ID.bc 25 26 27 
ID.ca 28 29 30 
ID.cb 31 32 33 
ID.cc 34 35 36 
ID.xx 40 40 55 
ID.xy 50 51 45 
.... 

MA應填充交叉信息。在我的例子應該看起來像對DF的所選列(比方說,1990年):

 a b c 
a 10 13 16 
b 19 22 25 
c 28 31 34 

我試圖使用匹配,但老實說它沒有工作:

MA$a = DF[match(MA.ID$a, DF$ID),2] 

我被推薦使用data.table包,但我看不出這對我有什麼幫助。

任何人有任何好辦法來解決這個問題?

+0

不應在第2行中的'預期輸出的了'柱'19'而不是'25'? – Jaap

+0

是的,絕對。謝謝你指出這個錯字! –

回答

2

假設你的輸入是dataframes,那麼你可以做到以下幾點:

library(data.table) 
setDT(ma)[, lapply(.SD, function(x) x = unlist(df[match(x,df$ID),"1990"])), 
      .SDcols=colnames(ma)] 

返回:

a b c 
1: 10 13 16 
2: 19 22 25 
3: 28 31 34 

說明

  • 隨着setDT(ma)你轉變將數據幀轉換爲數據表(其是增強型數據幀)。
  • 使用.SDcols=colnames(ma)您可以指定要應用轉換的列。
  • lapply(.SD, function(x) x = unlist(df[match(x,df$ID),"1990"])).SDcols指定的每列執行匹配操作。

data.table的另一種方法是首先轉化ma到長data.table

ma2 <- melt(setDT(ma), measure.vars = c("a","b","c")) 
setkey(ma2, value) # set key by which 'ma' has to be indexed 
setDT(df, key="ID") # transform to a datatable & set key by which 'df' has to be indexed 

# joining the values of the 1990 column of df into 
# the right place in the value column of 'ma' 
ma2[df, value := `1990`] 

其給出:

> ma2 
    variable value 
1:  a 10 
2:  b 13 
3:  c 16 
4:  a 19 
5:  b 22 
6:  c 25 
7:  a 28 
8:  b 31 
9:  c 34 

這個方法的唯一缺點是'值'列中的數值得到stor編輯爲字符值。您可以通過擴展它如下更正此:

ma2[df, value := `1990`][, value := as.numeric(value)] 

如果你想改回寬幅你可以使用從development version of data.table (v1.9.7+)rowid功能:

ma3 <- dcast(ma2, rowid(variable)~variable, value.var = "value")[, variable:=NULL] 

這給:

> ma3 
    a b c 
1: 10 13 16 
2: 19 22 25 
3: 28 31 34 

使用的數據

ma <- structure(list(a = structure(1:3, .Label = c("ID.aa", "ID.ba", "ID.ca"), class = "factor"), 
        b = structure(1:3, .Label = c("ID.ab", "ID.bb", "ID.cb"), class = "factor"), 
        c = structure(1:3, .Label = c("ID.ac", "ID.bc", "ID.cc"), class = "factor")), 
       .Names = c("a", "b", "c"), class = "data.frame", row.names = c(NA, -3L)) 

df <- structure(list(ID = structure(1:9, .Label = c("ID.aa", "ID.ab", "ID.ac", "ID.ba", "ID.bb", "ID.bc", "ID.ca", "ID.cb", "ID.cc"), class = "factor"), 
        `1990` = c(10L, 13L, 16L, 19L, 22L, 25L, 28L, 31L, 34L), 
        `1991` = c(11L, 14L, 17L, 20L, 23L, 26L, 29L, 32L, 35L), 
        `1992` = c(12L, 15L, 18L, 21L, 24L, 27L, 30L, 33L, 36L)), 
       .Names = c("ID", "1990", "1991", "1992"), class = "data.frame", row.names = c(NA, -9L)) 
+0

這絕對是處理我的問題的最佳方式,@Jaap!你的回答搖滾!非常非常感謝你!! –

+0

做到了:)再次感謝您! –

2

在基R,它可以被看作是一個工作於outer

> outer(1:nrow(MA.ID), 1:ncol(MA.ID), Vectorize(function(x,y) {DF[which(DF$ID==MA.ID[x,y]),'1990']})) 
    [,1] [,2] [,3] 
[1,] 10 13 16 
[2,] 19 22 25 
[3,] 28 31 34 

說明:

  • outer創建一個矩陣作爲第一個參數X的外積(這裏a b c)和第二個參數Y(這裏相同,a b c
  • for each com的XY bination,它適用於中查找在DF的價值,在其中IDMA.ID[X,Y]行的功能,並在列1990
  • 這裏最重要的訣竅是用Vectorize包裝的功能,因爲outer預期向量化函數
  • 結果最後返回作爲基質

或者,另一種方式來做到這一點(仍然在鹼R)是:

  1. 將數據幀MA.ID轉換成向量
  2. sapply快速功能查找對應關係與DF$ID
  3. 並重新轉換爲矩陣。

這工作:

> structure(
    sapply(unlist(MA.ID), 
      function(id){DF[which(DF$ID==id),'1990']}), 
    dim=dim(MA.ID), names=NULL) 

    [,1] [,2] [,3] 
[1,] 10 13 16 
[2,] 19 22 25 
[3,] 28 31 34 

(這裏的調用structure(..., dim=dim(MA.ID), names=NULL)向量轉換回矩陣)