【问题标题】:Summarise to return the length by group汇总以按组返回长度
【发布时间】:2019-05-10 08:08:00
【问题描述】:

我想在下面的数据框中添加一个新列,用于计算每个月的最大旱期长度。 这是我的数据框的样子:

   day month year  rr spell spell1
     1     1 1981  0   dry      1
     2     1 1981  0   dry      1
     3     1 1981  0   dry      1
     4     1 1981  1.1 dry      0
     5     1 1981  0   dry      1
     6     1 1981  0   dry      1
     7     1 1981  0   dry      1
     8     1 1981  0   dry      1
     9     1 1981  2.7 dry      0
    10     1 1981  0   dry      1

这是我需要的输出:

 month year  spell_length
     1 1981      3
     1 1981      4
     1 1981      1

这是我到目前为止所做的:

group_by(df, year, month, spell1) %>% 
    summarise(spell2 = sum(spell1, na.rm = TRUE))

结果如下:

  year month spell1 spell_length
  <int> <int>  <dbl>  <dbl>
1  1981     1      1     31
2  1981     2      0      0
3  1981     2      1     27
4  1981     3      0      0
5  1981     3      1     25
6  1981     4      0      0

数据

df <- read.table(h= T, text="day month year  rr spell spell1
1     1 1981  0   dry      1
2     1 1981  0   dry      1
3     1 1981  0   dry      1
4     1 1981  1.1 dry      0
5     1 1981  0   dry      1
6     1 1981  0   dry      1
7     1 1981  0   dry      1
8     1 1981  0   dry      1
9     1 1981  2.7 dry      0
10     1 1981  0   dry      1")

【问题讨论】:

  • 您能解释一下您的输出是如何实现的吗?比如rr是什么意思?
  • rr 表示降雨量值,spell == dry if rr spell1 == 1 if spell == dry else 0

标签: r dplyr


【解决方案1】:

一种选择是按 'spell' 的 'run-length-id' 分组(rleid from data.table - 当该列中的值更改时创建一个新的分组 id),filter 出行'spell1' 为 0,获取 n() 的行数

library(dplyr)
library(data.table)
df1 %>%
    group_by(year, month, grp = rleid(spell1)) %>%
    filter(spell1 ==1) %>%
    summarise(spell_length = n()) %>%
    ungroup %>%
    select(-grp)
# A tibble: 3 x 3
#   year month spell_length
#  <int> <int>        <int>
#1  1981     1            3
#2  1981     1            4
#3  1981     1            1

或者从base R使用rle

rl1 <- rle(df1$spell1)
rl1$lengths[rl1$values > 0]
#[1] 3 4 1

注意:当 'spell1' 值不同时,此解决方案也有效

【讨论】:

  • 谢谢阿克伦。您的建议非常有效。这正是我想要的。
【解决方案2】:

使用dplyr,我们可以使用cumsum在每次出现0时创建组,并将每个组中spells的数量相加。

library(dplyr)

df %>%
  group_by(month, year, group = cumsum(spell1 == 0)) %>%
  summarise(spell_length = sum(spell1)) %>%
  ungroup() %>%
  select(-group)

#    month  year spell_length
#   <int> <int>        <int>
#1     1  1981            3
#2     1  1981            4
#3     1  1981            1

【讨论】:

  • 这也很好用。我在group_by 中交换了monthyear 以保持数据的原始排列。谢谢@Ronak Shah。为什么最后使用ungroup()?。
  • @ahmadbello 如果你不做ungroup() 你前面做的所有计算都会被分组,它可能会影响你可能做的计算。所以从更安全的角度来看,最好ungroup 数据。
【解决方案3】:

使用@akrun 的基本思想,但没有data.table::rleid()

df %>%
 group_by(year, month, rleid = with(rle(spell1), rep(seq_along(lengths), lengths))) %>%
 filter(spell1 > 0) %>%
 ungroup() %>%
 count(month, year, rleid, name = "spell_length") %>%
 select(-rleid) 

  month  year spell_length
  <int> <int>        <int>
1     1  1981            3
2     1  1981            4
3     1  1981            1

或者:

df %>%
 group_by(year, month, rleid = with(rle(spell1), rep(seq_along(lengths), lengths))) %>%
 filter(spell1 > 0) %>%
 summarise(spell_length = length(rleid)) %>%
 ungroup() %>%
 select(-rleid)

【讨论】:

    【解决方案4】:

    这是一个使用 dplyr::count 的选项:

    library(dplyr)
    count(df, month, year, grp = cumsum(spell1 == 0), zero = spell1==0) %>%
      filter(!zero) %>%
      select(-zero, - grp)
    
    # # A tibble: 3 x 3
    #   month  year     n
    #   <int> <int> <int>
    # 1     1  1981     3
    # 2     1  1981     4
    # 3     1  1981     1
    

    或者在基础 R 中:

    res <- aggregate(day ~  month + year + cumsum(spell1 == 0) + (spell1==0), df, length)
    res[!res[[4]],-(3:4)]
    #   month year day
    # 1     1 1981   3
    # 2     1 1981   4
    # 3     1 1981   1
    

    【讨论】:

      猜你喜欢
      • 2019-02-24
      • 2016-07-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-12
      • 1970-01-01
      相关资源
      最近更新 更多