【问题标题】:dplyr: group variables then assign unique names based on unique groupingdplyr:分组变量然后根据唯一分组分配唯一名称
【发布时间】:2017-12-03 23:10:25
【问题描述】:

我有一个这样的数据框:

df<- data.frame(date= c(rep("10-29-16", 3), rep("11-14-16", 2),
                      "12-29-16","10-2-17","9-2-17"),
                loc= c(rep("A", 3), rep("B", 2),"A","PlotA","PlotB"), 
                obs_network= c(rep("NA", 3), rep("NA", 2),"NA","PlotA","PlotB"))

对于obs_network,即NA,我想为每个独特的dateloc 组合命名。我希望为唯一组分配一个唯一编号和此命名方案的前缀“pseudoplot”。所以输出看起来像这样:

output<- data.frame(date= c(rep("10-29-16", 3), rep("11-14-16", 2),
                      "12-29-16","10-2-17","9-2-17"),
                loc= c(rep("A", 3), rep("B", 2),"A","PlotA","PlotB"), 
                obs_network= c(rep("pseudoplot_1", 3),rep("pseudoplot_2", 2),"pseudoplot_3","PlotA","PlotB"))

我尝试了以下操作但没有成功,我无法识别我的错误。使用所有级别下方的代码读取“pseudoplot1”。如果有人解释了为什么我的代码除了提供解决方案之外无法正常工作,我将不胜感激。

output<-
  df %>%
  group_by(date, loc)%>%
  mutate(obs_network=ifelse(is.na(obs_network), 
                      paste0("pseudoplot", "_", match(loc, unique (loc))), 
                             obs_network))

【问题讨论】:

    标签: r dplyr


    【解决方案1】:

    这是我能想到的。有条件:1)date是一个日期对象,2)locobs_network是字符向量。我在下面创建了一个示例。 date 是日期对象,locobs_network 是字符向量。

             date   loc obs_network
    1  2016-10-29     A        <NA>
    2  2016-10-29     A        <NA>
    3  2016-10-29     A        <NA>
    4  2016-11-14     B        <NA>
    5  2016-11-14     B        <NA>
    6  2016-12-29     A        <NA>
    7  2017-10-02 PlotA       PlotA
    8  2017-09-02 PlotB       PlotB
    9  2017-10-10     A        <NA>
    10 2017-10-10     B        <NA>
    

    我用了两个东西。一是我使用了两个日期之间的差异。另一个是我使用差异来为 cumsum() 的唯一日期创建唯一的组号。通过粘贴唯一组号和loc,我创建了唯一组。

    mydf %>%
    mutate(obs_network = if_else(is.na(obs_network), 
                                 paste0("pseudoplot_", cumsum(c(T, abs(diff(date)) > 0)), loc, sep = ""),
                                 obs_network))
    
    
    #         date   loc   obs_network
    #1  2016-10-29     A pseudoplot_1A
    #2  2016-10-29     A pseudoplot_1A
    #3  2016-10-29     A pseudoplot_1A
    #4  2016-11-14     B pseudoplot_2B
    #5  2016-11-14     B pseudoplot_2B
    #6  2016-12-29     A pseudoplot_3A
    #7  2017-10-02 PlotA         PlotA
    #8  2017-09-02 PlotB         PlotB
    #9  2017-10-10     A pseudoplot_6A
    #10 2017-10-10     B pseudoplot_6B
    

    数据

    mydf <- structure(list(date = structure(c(17103, 17103, 17103, 17119, 
    17119, 17164, 17441, 17411, 17449, 17449), class = "Date"), loc = c("A", 
    "A", "A", "B", "B", "A", "PlotA", "PlotB", "A", "B"), obs_network = c(NA, 
    NA, NA, NA, NA, NA, "PlotA", "PlotB", NA, NA)), .Names = c("date", 
    "loc", "obs_network"), row.names = c(NA, -10L), class = "data.frame")
    

    【讨论】:

    • 我认为你写collapese = "" 的代码中可能有错字。无论哪种方式,都非常感谢您的帮助和建议。为了帮助我更好地理解您的方法,您介意解释一下cumsum(c(T, abs(diff(date) &gt; 0))) 的作用吗?
    • @Danielle 是的,这是一个错字。对不起。 cumsum() 的括号位置也错误。 cumsum(c(T, abs(diff(date)) &gt; 0)) 基本上是在创建一个组变量。 abs(diff(date)) &gt; 0 生成一个逻辑向量。每当两个日期之间的差异大于 0 时,您就会得到 TRUE。 c(T, abs(diff(date)) &gt; 0) 是一个逻辑向量。我添加了 T 以便编号从 1 开始。如果您首先有 F,编号从 0 开始。 cumsum() 正在创建一个分组变量。当从 T 变为 F 或反之亦然时,编号会增加 1。
    【解决方案2】:

    一些注意事项:

    1. 您已在数据框中包含 "NA" - 所以这些是文本(实际上是因素),实际上不是 NA 值。我建议更改您的原始数据框。

      df <- tibble(date= c(rep("10-29-16", 3), 
                               rep("11-14-16", 2),"12-29-16","10-2-17","9-2-17"),
                  loc= c(rep("A", 3), rep("B", 2), "A", "PlotA", "PlotB"), 
                  obs_network= c(rep(NA, 6), "PlotA", "PlotB"))
      
    2. 使用因子(您在数据库中创建的内容)和使用 ifelse 的字符向量或整数会出现问题。我已将数据集更改为 tibble,以便所有内容都是字符并且正在使用 if_else

    3. 最后不要使用 group_by 来保持一切平坦

      df %>% 
        mutate(obs_network = if_else(is.na(obs_network), 
                             paste0("pseudoplot", "_",  match(paste0(date,loc), unique(paste0(date,loc)))),
                             obs_network))
      

    【讨论】:

    • 这很好用。谢谢你。我确实将所有真实数据都转换为字符,所以我已经考虑过了。无论哪种方式,我都不知道您可以使用 tibble() 函数将 df 中的变量转换为字符。所以这也很有帮助!关于为什么使用 group_by() 不起作用的任何解释?
    • @Danielle 如果你使用group_by,那么每个组将只有一个唯一的 id,因此你所有的伪图都是 1。
    猜你喜欢
    • 1970-01-01
    • 2017-01-31
    • 2021-07-13
    • 2015-07-31
    • 1970-01-01
    • 1970-01-01
    • 2019-10-08
    • 2021-12-08
    • 2019-08-16
    相关资源
    最近更新 更多