创建间隔

时间:2021-07-03 00:38:30

标签: r tidyverse lubridate

我有一个数据集,我想将其拆分为 10 天的时间间隔。我在下面包含的代码可以做到这一点,但在过去一周左右的时间里,有些日子(例如,一个月的 31 日或 30 日)会自行结束。

我想删除创建此间隔的间隔或将它们包含在之前的间隔中。

例如: 如果我将 1 月按 10 天的间隔分开,它会将前 10 天放在列表的一个元素中,将第二个 10 天放在另一个元素中,将第三个 10 天放在另一个元素中。然后它会将 1 月 31 日单独放入列表元素中。

我想要的输出是从列表中删除这些元素,或者更优选地将它们包含在第三个 10 天间隔中。可以做到吗?如果是这样,最好的方法是什么?

library(lubridate)
library(tidyverse)
date <- rep_len(seq(dmy("26-12-2010"), dmy("20-12-2013"), by = "days"), 500)
ID <- rep(seq(1, 5), 100)

df <- data.frame(date = date,
                 x = runif(length(date), min = 60000, max = 80000),
                 y = runif(length(date), min = 800000, max = 900000),
                 ID)

int <- df %>%
  arrange(ID) %>% 
  mutate(new = ceiling_date(date, '10 day')) %>% 
  # mutate(cut = data.table::rleid(cut(new, breaks = "10 day"))) %>% 
  group_by(new) %>%
  group_split()

3 个答案:

答案 0 :(得分:2)

如果组中有一行,则为其提供前一个 new 值。试试这个 -

library(dplyr)
library(lubridate)

df %>%
  arrange(ID, date) %>% 
  mutate(new = ceiling_date(date, '10 day')) %>%
  add_count(new) %>%
  mutate(new = if_else(n == 1, lag(new), new)) %>%
  select(-n) %>%
  group_split(new)

以上仅适用于组合具有 1 个观察值的组。如果我们想合并超过 1 天,请使用以下代码来计算一组中的天数。如果天数小于 n 天数,则组合该组。

n <- 2

df %>%
  arrange(ID, date) %>% 
  mutate(new = ceiling_date(date, '10 day'), 
         ID = match(new, unique(new))) -> tmp
tmp %>%
  group_by(new, ID) %>%
  summarise(count_unique = n_distinct(date)) %>%
  ungroup %>%
  mutate(new = if_else(count_unique < n, lag(new), new)) %>%
  inner_join(tmp, by = 'ID') %>%
  select(new = new.x, date, x, y) %>%
  group_split(new)

答案 1 :(得分:2)

以下解决方案将月份按 10 天间隔拆分,但更正了 new 以将一个月的第 31 天分配给最后一个期间。所以,

  • 第 1 到 10 天属于一个月的前三分之一,
  • 第 11 到 20 天到第二个三分之一,以及
  • 第 21 天到第 31 天到第三个第三天。
int <- df %>%
  # arrange(ID) %>%   # skipped for readability of result
  mutate(new = floor_date(date, '10 day')) %>%
  mutate(new = if_else(day(new) == 31, new - days(10), new)) %>% 
  group_by(new) %>%
  group_split()

int[[1]]
<块引用>
# A tibble: 6 x 5
  date            x       y    ID new       
  <date>      <dbl>   <dbl> <int> <date>    
1 2010-12-26 71469. 819084.     1 2010-12-21
2 2010-12-27 69417. 893227.     2 2010-12-21
3 2010-12-28 70865. 831341.     3 2010-12-21
4 2010-12-29 68322. 812423.     4 2010-12-21
5 2010-12-30 65643. 837395.     5 2010-12-21
6 2010-12-31 63638. 892200.     1 2010-12-21

现在,2010-12-31 被分配到 12 月的第三个三分之一。

请注意,new 通过调用 floor_date() 而不是 ceiling_date() 表示区间的开始。这是为了避免跨月边界日算术的潜在问题,并澄清间隔所属的月份。例如,对于二月的最后一天,ceiling_date(ymd('2011-02-28'), '10 day') 返回“2011-03-03”,即三月的日期。

答案 2 :(得分:0)

替代方案

library(lubridate)
library(tidyverse)

dt <- rep_len(seq(dmy("26-12-2010"), dmy("20-12-2013"), by = "days"), 500)
ID <- rep(seq(1, 5), 100)

df <- data.frame(dt = dt,
  x = runif(length(dt), min = 60000, max = 80000),
  y = runif(length(dt), min = 800000, max = 900000),
  ID)
  1. 在最后三分之一中包括额外的天数(第 31 天)
int_df <- df %>%
  # arrange(ID) %>%
  mutate(day_date = day(dt),
    day_new = case_when(
      day_date <= 10  ~ 1,
      day_date <= 20  ~ 11,
      TRUE            ~ 21
    ),
    new = ymd(paste(year(dt), month(dt), day_new, sep = "-"))) %>% 
  select(-c(day_date, day_new)) %>% 
  group_by(new) %>%
  group_split()

int_df[[1]]
#> # A tibble: 6 x 5
#>   dt              x       y    ID new       
#>   <date>      <dbl>   <dbl> <int> <date>    
#> 1 2010-12-26 62395. 837491.     1 2010-12-21
#> 2 2010-12-27 66236. 836481.     2 2010-12-21
#> 3 2010-12-28 79918. 818399.     3 2010-12-21
#> 4 2010-12-29 67613. 807213.     4 2010-12-21
#> 5 2010-12-30 72980. 899380.     5 2010-12-21
#> 6 2010-12-31 61004. 876191.     1 2010-12-21
  1. 排除额外的天数(第 31 天)
int_df <- df %>%
  # arrange(ID) %>%
  mutate(day_date = day(dt),
    day_new = case_when(
      day_date <= 10  ~ 1,
      day_date <= 20  ~ 11,
      day_date <= 30  ~ 21,
      TRUE            ~ 31
    ),
    new = ymd(paste(year(dt), month(dt), day_new, sep = "-"))) %>% 
  filter(day_date != 31) %>% 
  select(-c(day_date, day_new)) %>%
  group_by(new) %>%
  group_split()

int_df[[1]]
#> # A tibble: 5 x 5
#>   dt              x       y    ID new       
#>   <date>      <dbl>   <dbl> <int> <date>    
#> 1 2010-12-26 62395. 837491.     1 2010-12-21
#> 2 2010-12-27 66236. 836481.     2 2010-12-21
#> 3 2010-12-28 79918. 818399.     3 2010-12-21
#> 4 2010-12-29 67613. 807213.     4 2010-12-21
#> 5 2010-12-30 72980. 899380.     5 2010-12-21

reprex package (v2.0.0) 于 2021 年 7 月 3 日创建

相关问题