2016-08-04 60 views
-1

我有一箇中央數據框架的信息(df3),我試圖根據從另一個列(df2)提取的數據進行子集和列添加, ,本身來自第三個(df1)的子集。我設法通過搜索幫助和各種功能來達到目的,但我陷入了僵局。我希望你能幫忙。從R數據框中的多列提取數據,然後搜索另一個

首先,在3dfs組成如下:

#df1 - my initial search database 
id <- c("id1", "id2", "id3", "id4", "id5", "id6", "id7", "id8") 
yesno <- c("Yes", "Yes", "Yes", "Yes", "No", "Yes", "Yes", "No") 
city <- c("London", "London", "Paris", "London", "Paris", "New York", "London", "London") 
df1 <- cbind(id, yesno, city) 
df1 <- as.data.frame(df1) 
df1 

#df2 - containing the data needed to search df3, but situated across columns 
id <- c("id1", "id2", "id3", "id4", "id5", "id6", "id7", "id8") 
twitter <- c("@one","", "@three", "@four", "", "", "@seven", "") 
email <- c("", "", "", "add4", "add5","", "add7", "") 
mail <- c("", "postcode2", "", "","","","","postcode8") 
df2 <- cbind(id, twitter, email, mail) 
df2 <- as.data.frame(df2) 
df2 

#df3 - the central df containing the data I wish to extract 
comms <- c("@one", "postcode2", "@three", "@four", "add4", "add5", "six" "@seven", "add7", "postcode2") 
target <- c("text1", "text2", "text3", "text4.1", "text4.2", "text5", "text6", "text7.1","text7.2", "text8") 
df3 <- cbind(comms,target) 
df3 <- as.data.frame(df3) 
df3 

DF1 DF2和之間的共同性在ID列中找到。到目前爲止,我已經能夠過濾df1並提取id,然後我使用它來對df2進行子集化。

df_search <- df1 %>% 
    filter(yesno == "Yes", city == "London") 

    df_search_ids <- df_search$id 

    df2_search <- df2 %>% 
    filter(id %in% df_search_ids) 
    df2_search 

     id twitter email  mail 
    1 id1 @one     
    2 id2    postcode2 
    3 id4 @four add4   
    4 id7 @seven add7  

我的問題是:DF2和DF3之間的公共數據通過DF2三個不同的列特(Twitter,電子郵件和郵件)傳播;這些列包含空白單元格和其他無關信息(例如'我不在Twitter上');最後df2中的一些條目(如上面的id4和id7)在df3中有多個條目。

我試圖達到的解決方案是,我想從df2的列twitter,電子郵件和郵件中提取所有實例,基於與從df1提取的id匹配,以便可以應用提取的信息到子集DF3,並最終導致新的DF(target_res),看起來像這樣:

id_res <- c("id1", "id2", "id4", "id4", "id7", "id7") 
    comms_res <- c("@one", "postcode2", "@four", "add4", "@seven", "add7") 
    target_res <- c("text1", "text2", "text4.1", "text4.2", "text7.1", "text7.2") 
    result_df <- cbind(id_res, comms_res, target_res) 
    result_df <- as.data.frame(result_df) 
    result_df 

     id_res comms_res target_res 
    1 id1  @one  text1 
    2 id2 postcode2  text2 
    3 id4  @four text4.1 
    4 id4  add4 text4.2 
    5 id7 @seven text7.1 
    6 id7  add7 text7.2  

這是一個動作,我將執行次數(基於DF1的不同探索),因此,最好將複製。

我希望這是對問題的明確解釋。

+0

查找df3中的重複項如何?你的df3有兩行'postcode2'。你想要兩個,第一個? – aichao

+0

感謝您的回覆。我希望來自df3的所有實例能夠在comms列中找到與df2中的twitter,email,mail列相匹配的內容。在comms列中有很多重複項,但目標中的實例是唯一的,所以我希望所有這些重複項都是唯一的。 –

+0

我正在玩str_match,但似乎無法讓它工作。 –

回答

2

的關鍵是使用tidyr::gather來收集twitter:mail列(從過濾df2_search)作爲行的新列comms下,然後再filter刪除空行""。那麼你的第二個管道可以是:

library(dplyr) 

result <- df2 %>% filter(id %in% df_search_ids) %>% 
        gather("source","comms",twitter:mail) %>% 
        filter(comms != "") %>% 
        inner_join(df3, by="comms") %>% 
        select(id_res=id,comms_res=comms,target_res=target) %>% 
        arrange(id_res) 

df3的查找是那麼inner_join通過comms,這使只有在這兩個數據幀匹配的行。其餘的格式化輸出result

有了這個,你應該用你的輸入得到:

print(result) 
## id_res comms_res target_res 
##1 id1  @one  text1 
##2 id2 postcode2  text2 
##3 id2 postcode2  text8 
##4 id4  @four text4.1 
##5 id4  add4 text4.2 
##6 id7 @seven text7.1 
##7 id7  add7 text7.2 
##Warning messages: 
##1: attributes are not identical across measure variables; they will be dropped 
##2: In inner_join_impl(x, y, by$x, by$y, suffix$x, suffix$y) : 
## joining character vector and factor, coercing into character vector 

編輯擺脫警告

如上可見一斑,有兩個警告從處理:

  1. 第一個是fr om gather,對此的解釋發現here
  2. 第二個是從inner_join

擺脫這兩種警告的簡單解決方案是將相關數據列從因子轉換爲字符向量。對於來自gather的警告,需要轉換twitter,emailmail,df2的列,並且從inner_join,需要轉換來自df3的列comms。這可以使用:

df2[,2:4] <- sapply(df2[,2:4], as.character) 
df3$comms <- as.character(df3$comms) 

在處理之前。

注意,result$comms_res列現在是一個字符向量,而不是從原來的df3$comms(實際上水平的因素,即使我們沒有轉換爲字符,其結果將是一個特徵向量,因爲inner_join它會爲我們的警告說)。如果我們不在乎保留result中的因素,這是可以的。但是,如果我們實際上做對一組從df3$comms我們要在result$comms_res保留可能級別的護理,那麼我們就需要首先從df3$comms之前保存這些轉換爲字符:

## save these levels before converting to characters 
df3.comms.levels <- levels(df3$comms) 
df3$comms <- as.character(df3$comms) 

,然後都轉換df3$commsresult$comms_res回一個因素與這些級別處理:

df3$comms <- factor(df3$comms, levels=df3.comms.levels) 
result$comms_res <- factor(result$comms_res, levels=df3.comms.levels) 

希望這有助於。

+0

非常感謝你,@aichao - 這很有效,你的解釋很有意義。 –

+0

不客氣。我會進一步編輯這個以擺脫這些警告,敬請關注。 – aichao

+0

會做。謝謝! –

相關問題