【问题标题】:Cumulative percentage per column of a dataframe数据框每列的累积百分比
【发布时间】:2021-03-08 11:02:27
【问题描述】:

我有一个数据框,其中包含多个站点的每个儒略日的每日温度。

最小的可重现示例data.frame:

TemperatureData <- data.frame(
    Julian_Day = 1:365,
    Station_1 = c(rnorm(1:365, mean=10, sd=2)),
    Station_2 = c(rnorm(1:365, mean=10, sd=2)),
    Station_3 = c(rnorm(1:365, mean=10, sd=2))
)

我想确定每个站点超过总累积值的规定百分比的儒略日,以及输出说明每个站点达到此累积值阈值时的儒略日。

例如,假设 Station 1 的总值为 4000,在 180 儒略天之后,累积值超过了设置的总值的 50% 阈值,并为 data.frame 的每一列重复(首选示例下面的输出)。

Station_1   Station_2   Station_3
180         183         179

我认为这会在某种程度上利用 cumsum 函数,但不确定如何实现它。有人可以帮忙吗?

如果这没有意义,请告诉我。

【问题讨论】:

    标签: r dataframe cumulative-sum


    【解决方案1】:

    基础 R 解决方案:

    TemperatureData <- data.frame(
        Julian_Day = 1:365,
        Station_1 = c(rnorm(1:365, mean=10, sd=2)),
        Station_2 = c(rnorm(1:365, mean=10, sd=2)),
        Station_3 = c(rnorm(1:365, mean=10, sd=2))
    )
    
    TemperatureData$Station_1 <- cumsum(TemperatureData$Station_1) / sum(TemperatureData$Station_1)
    TemperatureData$Station_2 <- cumsum(TemperatureData$Station_2) / sum(TemperatureData$Station_2)
    TemperatureData$Station_3 <- cumsum(TemperatureData$Station_3) / sum(TemperatureData$Station_3)
    
    
    results <- c(
      "Station 1" = TemperatureData$Julian_Day[TemperatureData$Station_1 >= .5][1],
      "Station 2" = TemperatureData$Julian_Day[TemperatureData$Station_2 >= .5][1],
      "Station 3" = TemperatureData$Julian_Day[TemperatureData$Station_3 >= .5][1]
    )
    results
    #> Station 1 Station 2 Station 3 
    #>       180       185       183
    

    tidyverse解决方案:

    library(dplyr)
    TemperatureData %>%
      summarize(across(matches("Station"), 
                       function(x) Julian_Day[cumsum(x) / sum(x) > .5][1]))
    

    data.table解决方案:

    library(data.table)
    
    setDT(TemperatureData)
    
    TemperatureData[, lapply(.SD, function(x) Julian_Day[cumsum(x) / sum(x) > .5][1]), 
                    .SDcols=patterns("Station")]
    

    【讨论】:

    • 您好文森特,非常感谢您的快速响应!只是一个简单的问题:我的实际 data.frame 中碰巧有一些 NaN 值。所以我的输出是返回这些电台的 NA 值,我在脚本中尝试过 na.rm=T ,但没有任何乐趣。有什么想法吗?
    • AFAICT,cumsum 函数没有 na.rm 参数。但是,如果您不想增加缺失值,您可以在使用我的函数之前简单地将所有 NAs 替换为 0。这样,cumsum 就不会在这些观察值上增加,您会找到正确的阈值。
    • 太棒了!现在效果很好。感谢您的帮助。
    • 酷!随意单击复选标记以接受您最终使用的答案。
    【解决方案2】:

    这是tidyverse 的方法。我想有一个更简单的方法,如果我想通了,我会贴出来。

    library(dplyr)
    library(tidyr)
    TemperatureData %>% 
      pivot_longer(cols = -Julian_Day, names_to = "Station") %>%
      group_by(Station) %>%
      arrange(Station, Julian_Day) %>%
      mutate(cumpct = cumsum(value) / sum(value)) %>%
      filter(cumpct >= 0.5) %>%
      slice(1) %>%
      pivot_wider(id_cols = 1, names_from = Station, values_from = Julian_Day)
    
    # A tibble: 1 x 3
      Station_1 Station_2 Station_3
          <int>     <int>     <int>
    1       184       181       181
    

    【讨论】:

      猜你喜欢
      • 2018-09-08
      • 2021-08-21
      • 2012-02-24
      • 1970-01-01
      • 2021-10-15
      • 2017-03-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多