【问题标题】:Add observation number by group in R [duplicate]在R中按组添加观察编号[重复]
【发布时间】:2021-06-04 07:08:34
【问题描述】:

这是一个愚蠢的问题,但我是 R 新手,如果我能弄清楚如何做到这一点,它会让我的生活变得更加轻松! 所以这里有一些示例数据

data <- read.table(text = "Category Y
 A 5.1
 A 3.14
 A 1.79
 A 3.21
 A 5.57
 B 3.68
 B 4.56
 B 3.32
 B 4.98
 B 5.82
 ",header = TRUE)

我想添加一个列来计算组内的观察次数。这是我想要的样子:

Category    Y    OBS
A          5.1    1
A          3.14   2
A          1.79   3
A          3.21   4
A          5.57   5
B          3.68   1
B          4.56   2
B          3.32   3
B          4.98   4
B          5.82   5

我试过了:

data <- data %>% group_by(Category) %>% mutate(count = c(1:length(Category)))

这只是创建另一个编号从 1 到 10 的列,并且

data <- data %>% group_by(Category) %>% add_tally()

这只是创建了所有 5s 的另一列

【问题讨论】:

    标签: r data-manipulation


    【解决方案1】:

    基础R:

    data$OBS <- ave(seq_len(nrow(data)), data$Category, FUN = seq_along)
    data
    #    Category    Y OBS
    # 1         A 5.10   1
    # 2         A 3.14   2
    # 3         A 1.79   3
    # 4         A 3.21   4
    # 5         A 5.57   5
    # 6         B 3.68   1
    # 7         B 4.56   2
    # 8         B 3.32   3
    # 9         B 4.98   4
    # 10        B 5.82   5
    

    顺便说一句:可以使用框架的任何列作为第一个参数,包括 ave(data$Category, data$Category, FUN=seq_along),但 ave 根据输入 class 选择其输出 class,因此使用字符串作为第一个参数将导致返回字符串:

    ave(data$Category, data$Category, FUN = seq_along)
    #  [1] "1" "2" "3" "4" "5" "1" "2" "3" "4" "5"
    

    虽然不令人发指,但它需要是一种有意的选择。由于您似乎想要该列中的整数,因此我选择了最简单的整数输入,整数输出方法。它也可以使用rep(1L,nrow(data)) 或任何整数且与帧中的行数相同的长度,因为seq_along(我选择的函数)不会在意。

    【讨论】:

    • 解释得很好,点赞
    • 这在类别不连续的情况下是否有效?
    • DanielO,是的,试试吧!有一些技术需要将Category 变量无间隙地聚集在一起,但我通常建议不要使用它们,而是更喜欢一些健壮的东西。这Sathish'sAnigoyal's 的答案都对类别中的无序具有鲁棒性;不幸的是,rle 不是,它在Category 中找到(相同的)运行,因此不幸的是,一个类别的损坏组将单独编号。
    【解决方案2】:
    library(data.table)
    setDT(data)[, OBS := seq_len(.N), by = .(Category)]
    data
       Category    Y OBS
     1:        A 5.10   1
     2:        A 3.14   2
     3:        A 1.79   3
     4:        A 3.21   4
     5:        A 5.57   5
     6:        B 3.68   1
     7:        B 4.56   2
     8:        B 3.32   3
     9:        B 4.98   4
    10:        B 5.82   5
    

    【讨论】:

    • 或者只是setDT(data)[, OBS = rowid(Category)]
    • @r2evans 好多了
    【解决方案3】:
    library(dplyr) 
    data %>% group_by(Category) %>% mutate(Obs = row_number()) 
    
    # A tibble: 10 x 3
    # Groups:   Category [2]
       Category     Y   Obs
       <chr>    <dbl> <int>
     1 A         5.1      1
     2 A         3.14     2
     3 A         1.79     3
     4 A         3.21     4
     5 A         5.57     5
     6 B         3.68     1
     7 B         4.56     2
     8 B         3.32     3
     9 B         4.98     4
    10 B         5.82     5
    

    data$OBS <- ave(data$Category, data$Category, FUN = seq_along)
    
    data
       Category    Y OBS
    1         A 5.10   1
    2         A 3.14   2
    3         A 1.79   3
    4         A 3.21   4
    5         A 5.57   5
    6         B 3.68   1
    7         B 4.56   2
    8         B 3.32   3
    9         B 4.98   4
    10        B 5.82   5
    

    【讨论】:

    • 当我尝试这样做时,我得到一个错误 Error: n() must be used only be used inside dplyr verbs.
    • @yaynikkiprograms,这表明您使用的 mutate 不是 dplyr::mutate,或者您没有逐字使用此代码。 (您不能在 mutate 或其他 dplyr 动词之外使用 row_number()。)
    • ave(rep(1, nrow(data)), data$Category, FUN=cumsum)
    • 您的第一个代码块可能最适合 OP,因为他们首先演示了 dplyr 尝试。
    【解决方案4】:

    另一个基础R

    category <- c(rep('A',5),rep('B',5))
    sequence <- sequence(rle(as.character(category))$lengths)
    data <- data.frame(category=category,sequence=sequence)
    head(data,10)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-31
      • 2021-06-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多