2016-08-04 63 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

会做。谢谢! –

相关问题