【问题标题】:Create an order of rows to keep in r based on column matches根据列匹配创建要保留在 r 中的行顺序
【发布时间】:2020-06-11 12:41:39
【问题描述】:

这是我的数据集的一部分:

df<-data.frame(
  group=c("A","A","A","A","B","B","C","C","D","D","E","F","G","G"), 
  first_name=c("Linda","Linda","Linda","Linda","Henry","Henry","Hazel","Hazel","Owen","Owen","Ava","Nora","Rose","Rose"),
  first_name_match=c("Linda","Linda", "John","John","Oliver","Oliver","Hazel","Violet","Owen","Owen/Ben","Ava",NA,"Alex/Rose","Alex"))

对于每个组,

1) 如果列 first_name 和 first_name 匹配相等(完全相同),则只保留这些行并删除其他行。

2) 如果列 first_name 和 first_name 匹配相等(完全相同),并且与其他行存在部分匹配。通过部分匹配,我的意思是 first_name_match 是否包含 first_name 的一部分,然后只获取完全匹配。

2)如果没有完全匹配(它们不相等),我想保留部分匹配的行。部分匹配是指 first_name_match 是否包含 first_name 的一部分。

3) 如果没有匹配/部分匹配 - 保留这些行并标记它们以供进一步理解

总的来说,我想保留完全匹配的顺序,如果没有完全匹配,则部分匹配,然后保留不匹配或不匹配的行。

请看输出:

df_final<-data.frame(
  group=c("A","A","B","B","C","D","E","F","G"), 
  first_name=c("Linda","Linda","Henry","Henry","Hazel","Owen","Ava","Nora","Rose"),
  first_name_match=c("Linda","Linda","Oliver","Oliver","Hazel","Owen","Ava",NA,"Alex/Rose"))

【问题讨论】:

  • 你需要定义'部分匹配'。
  • 部分匹配是名字是否在first_name_match中,例如单词Rose在Rose/Alex中。
  • 您提供的 df 不是可重现的代码:每列中的行数不同,我必须更正这一点。我也浪费时间找出“不是”。为了帮助其他人帮助您,请确保您发布的代码有效。
  • 当然,瓦尔迪。对此感到抱歉。

标签: r dplyr


【解决方案1】:
library(data.table)
library(dplyr)
df<-data.frame(
  group=c("A","A","A","A","B","B","C","C","D","D","E","F","G","G"), 
  first_name=c("Linda","Linda","Linda","Linda","Henry","Henry","Hazel","Hazel","Owen","Owen","Ava","Nora","Rose","Rose"),
  first_name_match=c("Linda","Linda", "John","John","Oliver","Oliver","Hazel","Violet","Owen","Owen/Ben","Ava",NA,"Alex/Rose","Alex"))%>% as.data.table()

#1 exact match
df1 <- df[first_name==first_name_match]

#2 partial match
df2 <- df[mapply(grepl,df$first_name,df$first_name_match)] 
df2 <- df2[!df1,on = .(group,first_name)]

#3 no match
df3 <- df[!rbind(df1,df2), on = .(group,first_name)]

#Result
result <- rbind(df1,df2,df3)
result

group first_name first_name_match
1:     A      Linda            Linda
2:     A      Linda            Linda
3:     C      Hazel            Hazel
4:     D       Owen             Owen
5:     E        Ava              Ava
6:     G       Rose        Alex/Rose
7:     B      Henry           Oliver
8:     B      Henry           Oliver
9:     F       Nora             <NA>

【讨论】:

  • 所以我不希望 Owen/Ben 在输出中,因为它不是完全匹配的。而且我仍然想要返回 NA 或不匹配的行。
  • @Ashti,请花时间清楚地表达您的问题:如果您这样做,您将得到您期望的解决方案。
  • 感谢您提供更新的解决方案。我认为代码的第一行应该是:df1
  • 我在data.table中转换了df,所以语法是正确的,见intro to data.table。我只是忘记包含 library(dplyr) 以便理解 %>% as.data.table() 。已更正
【解决方案2】:

您可以编写一个函数来根据条件为每个组选择行。

library(dplyr)
library(stringr)

select_rows <- function(x, y) {
   #If any exact match is found return exact match
   if(any(x == y, na.rm = TRUE)) x == y
   #else if partial match is found return partial match
   else if(any(str_detect(y, x), na.rm = TRUE)) str_detect(y, x)
   #If none of the above then return all rows
   else TRUE
}

并按组应用此功能。

df %>% group_by(group) %>% filter(select_rows(first_name, first_name_match))


# group first_name first_name_match
#  <chr> <chr>      <chr>           
#1 A     Linda      Linda           
#2 A     Linda      Linda           
#3 B     Henry      Oliver          
#4 B     Henry      Oliver          
#5 C     Hazel      Hazel           
#6 D     Owen       Owen            
#7 E     Ava        Ava             
#8 F     Nora       NA              
#9 G     Rose       Alex/Rose       

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-05-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-11
    • 2017-06-03
    • 1970-01-01
    相关资源
    最近更新 更多