【问题标题】:Conditional replacement of character variable in RR中字符变量的条件替换
【发布时间】:2015-08-23 03:23:18
【问题描述】:

我有一个包含许多列的数据集,但我只会提及此操作所需的那些并提供一个临时的(我也相信您不需要我刚刚包含的 ID 信息以便更容易理解) .

Business Division | Local Claim ID| CMB
       GC                123         **Y**       
       GC                124         N
       NAC               125         N
       NAC               126         N
       NAC               127         **Y**
       GC                128         N

我想去掉 CMB 列,而如果原始值为 Y,我将替换每个业务部门的 CMB 值,基本上我希望表格如下所示:(Business Divison now 3 classes)

Business Division | Local Claim ID
       **CMB**           123             
       GC                124        
       NAC               125        
       NAC               126        
       **CMB**           127        
       GC                128      

这是dput 的输出以重现我的数据:

structure(list(Business.Division = c("CMB", "GC", "NAC", "NAC", 
"CMB", "GC"), Local.Claim.ID = 123:128, CMB = c("Y", "N", 
"N", "N", "Y", "N")), .Names = c("Business.Division", "Local.Claim.ID", 
"CMB"), row.names = c(NA, -6L), class = "data.frame")

【问题讨论】:

    标签: r replace conditional


    【解决方案1】:

    试试:

    df %>% 
      mutate(Business.Division = replace(Business.Division, which(CMB == 'Y'), 'CMB')) %>% 
      select(-CMB)
    

    这给出了:

    #  Business.Division Local.Claim.ID
    #1               CMB            123
    #2                GC            124
    #3               NAC            125
    #4               NAC            126
    #5               CMB            127
    #6                GC            128
    

    基准测试

    更新以添加对基准的建议:

    df <- data.frame(Business.Division = sample(c("GC", "NAC"), 10e6, replace = TRUE),
                     Local.Claim.ID = sample(100:199, 10e6, replace = TRUE),
                     CMB = sample(c("Y", "N"), 10e6, replace = TRUE),
                     stringsAsFactors = FALSE)
    
    library(microbenchmark)
    mbm <- microbenchmark(
      me = mutate(df, Business.Division = replace(Business.Division,which(CMB == "Y"), "CMB")),
      stevensp = (df$Business.Division <- ifelse(df$CMB == "Y", "CMB", df$Business.Division)),
      mts = (df$Business.Division[which(df$CMB == "Y")] = "CMB"),
      david1 = setDT(df)[CMB == "Y", Business.Division := "CMB"],
      david2 = setkey(setDT(df), CMB)[.("Y"), Business.Division := "CMB"],
      times = 10
    )
    

    David 的速度要快得多:

    > mbm
    Unit: milliseconds
         expr        min         lq       mean     median         uq        max neval cld
           me  496.79251  556.70752  592.35165  608.23875  634.88809  661.33805    10  b 
     stevensp 3449.53516 3518.47649 3585.91006 3572.62433 3681.19332 3718.06284    10   c
          mts  591.22479  654.01000  661.02210  661.41281  679.53060  719.74752    10  b 
       david1   58.67554   62.15468   66.85337   62.31426   62.99337   92.49148    10 a  
       david2   86.04280   89.42500  117.76540   89.61656   89.79652  232.45398    10 a  
    

    【讨论】:

    • 或者另一个选项是replace,即df %&gt;% mutate(Business.Division= replace(Business.Division, which(CMB=='**Y**'), '**CMB**')) %&gt;% select(-CMB)
    • @akrun 确实用替换好多了。将进行相应的编辑。
    • 这还没有拉动重型机械(二进制连接)。此外,很好的证明ifelse 是纯粹的****。我想知道setkey(setDT(df), CBM)[.("Y"), Business.Division := "CMB"] 将如何扩展。
    • @DavidArenburg 它实际上有点慢。我会更新基准。
    【解决方案2】:

    如果您只想评估相关行并就地更新,我会选择data.table

    library(data.table)
    setDT(df)[CMB == "Y", Business.Division := "CMB"][, CMB := NULL]
    #    Business.Division Local.Claim.ID
    # 1:               CMB            123
    # 2:                GC            124
    # 3:               NAC            125
    # 4:               NAC            126
    # 5:               CMB            127
    # 6:                GC            128
    

    【讨论】:

    • setDT(df)[CMB == "Y", Business.Division := "CMB"][, CMB := NULL] Error in any_na(as_list(RHS)) : object 'CanyNA' not found;我错过了包裹的一部分吗?
    • @plafort 不知道您为什么会收到此错误。我已经加载了没有* btw 的数据,因为 OP 仅使用它们来说明所需的值。另外,也许更新你的data.table 包。
    【解决方案3】:

    或者(仅当businessdivision 不是factor 时才有效)

    df$businessdivision[which(df$CMB == "Y")] = "CMB"
    

    【讨论】:

    • 这只有在businessdivision 不是一个因素时才有效
    • 真的,我假设一个data.frame
    • 我们都假设data.frame。我们还能假设什么?
    【解决方案4】:

    您可以单独使用ifelse(无需任何额外的软件包)来实现此目的:

    df$Business.Division = ifelse(df$CMB == "Y", "CMB", df$Business.Division)
    

    正如 DavidArenburg 在下面的 cmets 中指出的那样,这对于处理大数据效率不高。但是,如果您的数据不是很大,这是一个不错的简单方法。

    【讨论】:

    • 此代码已被 StevenBeaupre 在mutate 中使用。我猜你想传达的信息是ifelse 可以在没有任何附加包的情况下使用?
    • @akrun 是的,完全正确。这是一个非常基本的任务(变量值的条件替换)——并且可以只使用基本 R 来完成。不过,我编辑了我的答案以使其更清楚!
    • 这是一项基本任务,但对于大数据而言效率非常低,请参阅here。如果 OP 有 character 向量而不是 factor,@mts 解决方案会更可取
    • @DavidArenburg - 真的!
    猜你喜欢
    • 2021-10-19
    • 2019-09-15
    • 2022-01-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-21
    • 2012-07-07
    • 1970-01-01
    相关资源
    最近更新 更多