从R数据框中的多个列中提取数据,然后搜索另一个

时间:2016-08-04 16:42:19

标签: r search dplyr extract

我有一个中央数据信息框架(df3),我正在尝试根据从另一列(df2)的几列中提取的数据进行子集和添加列,本身来自第三个子集(df1)。我已经设法通过搜索帮助和玩各种功能到目前为止,但我已陷入僵局。我希望你能提供帮助。

首先,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上”);最后,df2中的一些条目(例如上面的id4和id7)在df3中有多个条目。

我想要达到的解决方案是,我想根据与从df1中提取的ID的匹配,从df2的列,电子邮件和邮件中提取所有实例,以便可以将提取的信息应用于子集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的不同探索),因此理想情况下是可复制的。

我希望这是对这个问题的明确解释。

1 个答案:

答案 0 :(得分:2)

关键是使用tidyr::gathertwitter: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. 第一个来自gather,找到的解释为here
  2. 第二个来自inner_join
  3. 摆脱这两种警告的一个简单的解决方案是将相关数据列从因子转换为字符向量。对于来自gather的警告,需要转换来自twitter的{​​{1}},emailmail列,以及df2,需要转换inner_join中的comms列。这可以使用:

    完成
    df3

    处理前。

    请注意,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$comms转换回处理后这些级别的因素:

    result$comms_res

    希望这有帮助。