我有一个中央数据信息框架(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的不同探索),因此理想情况下是可复制的。
我希望这是对这个问题的明确解释。
答案 0 :(得分: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
编辑以消除警告
如上所述,处理中有两个警告:
gather
,找到的解释为here。inner_join
。摆脱这两种警告的一个简单的解决方案是将相关数据列从因子转换为字符向量。对于来自gather
的警告,需要转换来自twitter
的{{1}},email
和mail
列,以及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
希望这有帮助。