【问题标题】:How to calculate count by group, then keep only one per group如何按组计算计数,然后每组只保留一个
【发布时间】:2015-07-22 05:15:43
【问题描述】:

说我有这个data.frame,data

data <- data.frame(val=c(rep(6,10), rep(7, 15), rep(8, 20), rep(9, 25), rep(10, 100), rep(11, 20), rep(12, 15), rep(13, 10)))
data$plus <- data$val + 100

我的目标是创建一个新的data.frame,其中包含每个val 的频率以及相关的plus 值。

我目前的策略是创建一个表(称为table),然后合并频率。然后只保留每组中的第一个观察结果:

table <- table(data$val)
df1 <- data.frame(val = as.integer(names(table)[1:length(table)]), N = table[1:length(table)])
df2 <- merge(data, df1)
df3 <- do.call(rbind, by(df2, list(df2$val), FUN=function(x) head(x, 1)))

这可行,但看起来很笨重。

例如,在 Stata 中,它会是更少更简单的代码。比如:

bys val plus: egen max = _N
bys val plus: gen first = _n==1
keep if first==1

有没有办法简化或使 R 代码更优雅?

【问题讨论】:

    标签: r merge data.table aggregate


    【解决方案1】:

    已编辑

    或者你可以使用aggregate()

    data$N = 0
    out = aggregate(N ~ val + plus, data = data, length)
    

    否则

    out = aggregate(plus ~val, data = data,function(x) c(unique(x), N = length(x)))
    do.call(data.frame, out)
    

    或使用ddply

    library(plyr)
    out = ddply(data, .(val,plus), summarize, N = length(plus))
    
    #> out
    #  val plus   N
    #1   6  106  10
    #2   7  107  15
    #3   8  108  20
    #4   9  109  25
    #5  10  110 100
    #6  11  111  20
    #7  12  112  15
    #8  13  113  10
    

    【讨论】:

    • ...请注意您将矩阵作为新“列”。
    • 更新的问题在于它依赖于“加号”,每个“val”只有一个(重复)值。示例就是这种情况,但我怀疑 OP 的原始数据就是这种情况。一个更简单的解决方案是采用您的原始解决方案并将其包装在 do.call(data.frame, yourOriginalCode) 中。
    • 是的,如果原始数据不同,您是对的。我已在答案中添加了您的建议
    【解决方案2】:

    这是一种使用“data.table”的方法:

    library(data.table)
    as.data.table(data)[, N := .N, by = val][, .SD[1], by = val]
    #    val plus   N
    # 1:   6  106  10
    # 2:   7  107  15
    # 3:   8  108  20
    # 4:   9  109  25
    # 5:  10  110 100
    # 6:  11  111  20
    # 7:  12  112  15
    # 8:  13  113  10
    
    ## Or (@RicardoSaporta)
    as.data.table(data)[, list(.N, plus=plus[1]), by = val]
    
    ## Or (@DavidArenburg)
    unique(as.data.table(data)[, N := .N, by = val], by = "val")
    

    使用“dplyr”,您可以尝试:

    library(dplyr)
    
    data %>%
      group_by(val) %>%
      mutate(N = n()) %>%
      slice(1)
    

    在基础 R 中,我想您可以尝试以下方法:

    do.call(rbind, lapply(split(data, data$val), 
                          function(x) cbind(x, N = nrow(x))[1, ]))
    

    【讨论】:

    • 如果你的数据比较大,下面的会快一点(虽然代码有点麻烦):as.data.table(data)[, list(.N, plus=plus[1]), by = val]
    • unique(as.data.table(data)[, N := .N, by = val], by = "val")
    • data %&gt;% group_by(val, plus) %&gt;% summarise(N = n())
    • @StevenBeaupré,我不想假设这些数据真的代表了 OP 的数据....(换句话说,我不想假设它们有一堆重复的值对于每个“var”)。
    • 我认为 OP 想要 (val, plus) 的频率(组大小),不?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-07
    • 2018-04-06
    • 1970-01-01
    • 1970-01-01
    • 2019-08-22
    相关资源
    最近更新 更多