【问题标题】:R - running into duplication error when mergingR - 合并时遇到重复错误
【发布时间】:2017-05-19 14:44:31
【问题描述】:

我有一个数据集,它告诉我客户电子邮件、客户编号以及他们是否是管理员。我们需要在同一记录中提供客户管理员的电子邮件,我们可以从数据中得出这一点,因为只要记录的客户编号等于管理员记录的编号,就将管理员的电子邮件放在该行中。此外,“第二位管理员”应该在“管理员电子邮件”字段中显示他自己的电子邮件,而不是该客户的“第一位管理员”。

我通过将管理员子集到一个新的数据帧中,然后合并管理员数据集和客户编号上的原始数据集来实现这一点。问题是当客户有 2 个管理员时,因为加入导致重复记录。有没有办法解决这个问题,比如“如果为 1 个客户列出了 2 个管理员,请使用第一个管理员电子邮件”?

##sample Data
    df <- data.frame(Email = c("test1@gmail.com", "test2@gmail.com", "test3@gmail.com","test4@gmail.com","test5@gmail.com","test6@gmail.com", "test7@gmail.com"),
                     Admin = c("Y", "N", "N","Y","N", "Y", "N"),
                     CustNum = c("1111","1111","1111","2222","2222","2222", "2222"))

##My solution
admins <- subset(df, df$Admin == "Y")
output <- merge(df, admins, by = "CustNum", all.x = TRUE)
colnames(output)[colnames(output)=="Email.y"] <- "Admin_Email"


    expected <- data.frame(Email = c("test1@gmail.com", "test2@gmail.com", "test3@gmail.com","test4@gmail.com","test5@gmail.com","test6@gmail.com", "test7@gmail.com"),
                           Admin = c("Y", "N", "N","Y","N", "Y", "N"),
                           CustNum = c("1111","1111","1111","2222","2222","2222", "2222"),
                     Adminemail = c("test1@gmail.com","test1@gmail.com","test1@gmail.com","test4@gmail.com","test4@gmail.com","test6@gmail.com", "test4@gmail.com"))

【问题讨论】:

  • 所以你想保持 x 不变?
  • 或者您只想添加列 ''Admin_email ?
  • 对不起@NicoCoallier 我是该网站的新手,忽略了您的 cmets(直接转到答案 :) .. 我想保持 x 完整并添加“管理员电子邮件”列,最终结果是相同(正确)数量的用户分配了相应的管理员电子邮件。谢谢!
  • 我的回答满意吗?

标签: r join merge


【解决方案1】:

如果不使用循环,我找不到解决方案,但它有效,试试这个。

## sample Data
df <- data.frame(Email = c("test1@gmail.com", "test2@gmail.com", "test3@gmail.com","test4@gmail.com","test5@gmail.com","test6@gmail.com", "test7@gmail.com"),
             Admin = c("Y", "N", "N","Y","N", "Y", "N"),
             CustNum = c("1111","1111","1111","2222","2222","2222", "2222"))

## My solution
library(dplyr)
admins <- df %>% filter(Admin == 'Y') %>% 
    select(Email, Admin, CustNum) %>% 
    mutate(AdminEmail = Email)
# find the first match for each unique CustNum
ind = sapply(unique(admins$CustNum), function(x) which(admins$CustNum == x)[1])
first_match = admins[ind, ]
# merge data
output = full_join(df, admins, by = c('Email', 'CustNum', 'Admin'))
# fill in NAs
for (i in 1:nrow(output)) {
    if (is.na(output$AdminEmail[i])) {
        output$AdminEmail[i] = first_match$AdminEmail[which(first_match$CustNum == output$CustNum[i])]
    }
}

【讨论】:

    【解决方案2】:

    我认为最简单的方法是使用 for 循环。但是 data.table 有一种方法,但我可以弄清楚...

    可行的解决方案但不是最佳的

    df$Adminemail = NA
    
    for(i in 1:nrow(df)){
    
        ### If the admin is himself then :
        if(df$Admin[i] == "Y"){
        df$Adminemail[i] = as.character(df$Email[i])
        }
    
        ### Otherwise it fill up with the first admin-email found
        else{
        sub <- df[df$CustNum == df$CustNum[i],]
        df$Adminemail[i] <- as.character(sub[sub$Admin=="Y",]$Email[1])
        }
        }
    

    如果您的数据集很大,for 循环可能会给您带来一些问题。但是,如果您可以创建一个唯一的 ID。我很确定 data.table 是一些更好、更优化的解决方案。

    不可行的解决方案但可能是更好的途径

      df$Unique <- paste(df$Email,df$CustNum,sep="_")
    
    
      library(data.table)
      setDT(df) 
      setDT(admins)
    
      # inner join - use `nomatch` argument
      admins[df, nomatch=0L, on = "Unique"]
    

    我在post找到了这段代码

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-02-27
      • 2018-07-29
      • 2019-05-16
      • 1970-01-01
      • 2018-08-03
      • 1970-01-01
      相关资源
      最近更新 更多