2016-08-25 48 views
3

使用2分公共列替換與DF1真值DF2錯誤的價值觀我有這樣由R中

TEAM <- c("PE","PE","MPI","TDT","HPT") 
EmpID <- c (444452,444456,16822,339862,14828)  
ManagerID <- c(11499,11599,11899,11339,11559) 
CODE <- c("F",NA,"A","H","G") 
df1 <- data.frame(TEAM,EmpID,ManagerID,CODE) 

TEAM <- c("MPI","TDT","HPT","PE","TDT","PE","MPI","TDT","HPT","PE") 
EmpID <- c(444452,444452,444452,339862,339862,16822,339862,16822,14828,14828) 
ManagerID <- c(11499,11499,11499,11339,11339,11899,11339,11899,11559,11559) 
CODE <- c("A234","H665","G654","F616","H626","F234","H695","G954","G616",NA) 
df2 <- data.frame(TEAM,EmpID,ManagerID,CODE) 

我試圖與更新DF2經理ID &的EmpID的錯誤值2個的數據幀只有當TEAM & CODE(在df1的CODE列中的字母與在df2中的CODE列的第一個字母相匹配)時,ManagerID爲& EmpID的真實值纔在df1中。如果團隊匹配但代碼不正確,那麼錯誤的值將保留並且不應該用來自df1的值替換。

我期望的輸出是

TEAM EmpID ManagerID CODE 
1 MPI 16822  11899 A234 
2 TDT 339862  11339 H665 
3 HPT 14828  11559 G654 
4 PE 444452  11499 F616 
5 TDT 339862  11339 H626 
6 PE 444452  11499 F234 
7 MPI 339862  11339 H695 
8 TDT 16822  11899 G954 
9 HPT 14828  11559 G616 
10 PE 444452  11599 <NA> 

你可以看到,該行7 & 8保持不變,因爲代碼不匹配。

我試圖這樣做是爲了我的previous question

df2$ManagerID = df1$ManagerID[match(substr(df2$CODE, 1, 1), df1$CODE)] 
df2$EmpID = df1$EmpID [match(substr(df2$CODE, 1, 1), df1$CODE)] 

這樣從格雷戈爾的幫助,我不知道如果我在正確的方向我領導。請幫助我瞭解如何有效地解決這個問題。

+1

編輯:-)謝謝弗蘭克 – Sharath

+0

我對你想要的輸出有點困惑。 'df1'中的'CODE'列應該使得'df2'中只有一行被改變('CODE'中''的那一行)。如果其他行沒有匹配的'CODE',其他行如何更改? – Warner

+0

我在那裏提到df1中CODE中的字母應該與df2中CODE中的第一個字母相匹配。 – Sharath

回答

1

既然你在這裏做文字子集,我會初始化爲特徵向量,而不是因素:

df1 <- data.frame(TEAM,EmpID,ManagerID,CODE, stringsAsFactors = FALSE) 
df2 <- data.frame(TEAM,EmpID,ManagerID,CODE, stringsAsFactors = FALSE) 

然後我會用數據表(不是必須的,但清潔劑):

library(data.table) 

# convert data frames to data.table 
setDT(df1) 
setDT(df2) 

您想要創建一個具有合併值的列,只需輸入df2的第一個字符即可CODE

df2[ , C_SHORT := substr(CODE,1,1)] 

然後我們合併TEAM/CODE組合中的兩個數據幀。這創建了NA,其中不存在任何匹配。然後,測試,如果任何列是NA,並插入初始值,如果他們是

merge(x = df2,y = df1, by.x = c("TEAM","C_SHORT"), by.y = c("TEAM","CODE"), all.x = TRUE)[ 
    , 
    .(
    TEAM, 
    EmpID = ifelse(is.na(EmpID.y), EmpID.x, EmpID.y), 
    ManagerID = ifelse(is.na(ManagerID.y), ManagerID.x, ManagerID.y), 
    CODE 
) 
    ] 
    TEAM EmpID ManagerID CODE 
1: HPT 14828  11559 G654 
2: HPT 14828  11559 G616 
3: MPI 16822  11899 A234 
4: MPI 339862  11339 H695 
5: PE 444456  11599 NA 
6: PE 444452  11499 F616 
7: PE 444452  11499 F234 
8: TDT 16822  11899 G954 
9: TDT 339862  11339 H665 
10: TDT 339862  11339 H626 

一個注意:您在這裏使用NA作爲查找這裏。這在合併函數(我沒有意識到)中起作用,但IMO這是不好的做法(R中的NA確實指的是丟失的數據,而在這裏它編碼了某些東西)。我會考慮改變你的數據如何表現。