【问题标题】:create a variable separately but uniquely for each `id` in a data.frame in R为 R 中的 data.frame 中的每个“id”单独但唯一地创建一个变量
【发布时间】:2019-08-13 20:15:11
【问题描述】:

我有一个data.frame 有两个变量esid。我想添加一个名为weeks 的新变量。但我想单独创建weeks,但对每个id 都是唯一的。

例如,如果 es == "SHORT" 对于所有 id == 1 的行,我想要相同的数字(例如,3)。如果 id == 2 是不同的数字(例如,1)。

我能否在 BASE R 中实现这一点(请参阅下面的所需输出结构

注意:SHORT < DEL1 < DEL2 以每个id 下的数值表示。

下面是我试过的数据和代码,没有成功:

D <- data.frame(es = c("SHORT", "SHORT", "SHORT","DEL1", "DEL1","DEL1","SHORT", 
            "SHORT", "SHORT", "DEL1", "DEL1", "DEL1","DEL2","DEL2","DEL2"),

                id = c(rep(1, 6), rep(2, 9)) ) 


weeks <- ifelse(D$es == "SHORT", sample(1:5, 6, T), ifelse(D$es == "DEL1", 
                                                        sample(4:8, 7, T),
                                                        sample(7:12, 2, T)))

所需的输出结构(数值是随机的):

   es  id   weeks
SHORT  1     3
SHORT  1     3
SHORT  1     3
 DEL1  1     5
 DEL1  1     5
 DEL1  1     5
SHORT  2     1
SHORT  2     1
SHORT  2     1
 DEL1  2     6
 DEL1  2     6
 DEL1  2     6
 DEL2  2     8
 DEL2  2     8
 DEL2  2     8

【问题讨论】:

  • 创建一个查找data.frame然后使用merge
  • 试试D_lookup &lt;- unique(D); D_lookup$weeks &lt;- c(3, 5, 1, 6, 8); out &lt;- merge(D, D_lookup), out[order(out$id, out$weeks), ]
  • 查看我更新的评论。
  • (刚刚从merge 发现了sort 参数。)

标签: r function dataframe lapply


【解决方案1】:

基本上是@markus 的建议。如果您需要随机的周数,可以将seq_along 替换为sample 或其他函数。

D <- data.frame(es = c("SHORT", "SHORT", "SHORT","DEL1", "DEL1","DEL1","SHORT", 
                       "SHORT", "SHORT", "DEL1", "DEL1", "DEL1","DEL2","DEL2","DEL2"),

                id = c(rep(1, 6), rep(2, 9)) ) 

weeksTbl <- unique(D)
weeksTbl$weeks <- seq_along(weeksTbl[[1]])

merge(D, weeksTbl, all = TRUE, sort = FALSE)

#>       es id weeks
#> 1  SHORT  1     1
#> 2  SHORT  1     1
#> 3  SHORT  1     1
#> 4   DEL1  1     2
#> 5   DEL1  1     2
#> 6   DEL1  1     2
#> 7  SHORT  2     3
#> 8  SHORT  2     3
#> 9  SHORT  2     3
#> 10  DEL1  2     4
#> 11  DEL1  2     4
#> 12  DEL1  2     4
#> 13  DEL2  2     5
#> 14  DEL2  2     5
#> 15  DEL2  2     5

【讨论】:

    【解决方案2】:

    考虑 diffcumsum 来对不同分组进行顺序排序:

    set.seed(8132019)
    rand <- sample(1:10, 10, replace=FALSE)
    
    D <- within(D, {        
              diff <- c(0,diff(es)) + c(0, diff(id))
              weeks <- cumsum(ifelse(diff == 0, 0, 1)) + 1
    
              rm(diff)
        })
    
    D
    #       es id weeks
    # 1  SHORT  1     1
    # 2  SHORT  1     1
    # 3  SHORT  1     1
    # 4   DEL1  1     2
    # 5   DEL1  1     2
    # 6   DEL1  1     2
    # 7  SHORT  2     3
    # 8  SHORT  2     3
    # 9  SHORT  2     3
    # 10  DEL1  2     4
    # 11  DEL1  2     4
    # 12  DEL1  2     4
    # 13  DEL2  2     5
    # 14  DEL2  2     5
    # 15  DEL2  2     5
    

    【讨论】:

    • 确保它是由id 订购的,否则你可能会在diff(id) 中得到一个-1,而在diff(es) 中取消一个1 以获得0 的差异(未能增加cumsum)
    • 好点@IceCreamToucan。 Reza,这个解决方案应该以任何字符组顺序工作,因为它检查两列中的差异:esid
    • 实际上@IceCreamToucan,我先用 1 的 id 进行测试,然后再用 0 进行测试,解决方案仍然成立:rextester.com/GMO24389
    • 原帖没有提到排序,而是随机数分组。然后只需删除随机数:weeks &lt;- cumsum(diff)+1。见编辑。
    • 这是一个与排序相关的示例:获取原始数据,然后运行D$id[D$id == 2] &lt;- -1,然后运行within 代码
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-27
    • 2019-06-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多