• R语言
  • 如何将一行代表持续天数的序列 4,3,1,1,0 转换成每天出现频次 1,2,2,3,0

如何将数值转换成频次并求和

现在有一列时间序列数据 4,3,1,1,0

Date <- c("06-01","06-02","06-03","06-04","06-04")
Last_day <- c(4,3,1,1,0)
Data1 <- data.frame(Date,Last_day)
Data1
   Date Last_day
1 06-01        4
2 06-02        3
3 06-03        1
4 06-04        1
5 06-04        0

数字代表从该天开始持续的天数
我想最后求得每天出现的频次是多少

Count_day <- c(1,2,3,3,0)
Data2 <- data.frame(Date,Last_day,Count_day)
Data2
   Date Last_day Count_day
1 06-01        4         1
2 06-02        3         2
3 06-03        1         3
4 06-04        1         3
5 06-04        0         0

我想的逻辑是
4,3,1,1,0=
1,1,1,1,0 +
0,1,1,1,0 +
0,0,1,0,0 +
0,0,0,1,0 +
0,0,0,0,0 =
1,2,3,3,0.
但是不知如何实现。

你这方法可以啊,你自己不是已经写的很清楚了吗?1、构造矩阵;2、对矩阵按行求和。

再提供一个思路:对当前行之前的所有行计算其 index 和 last_day 的和,然后跟当前行的 index 比较,统计 大于当前行index 的行的数量。

    CMCai0104
    但是我不知道怎么构建这个矩阵啊 就对R的掌握程度还没有达到可以编出来的地步

    Date <- c("06-01","06-02","06-03","06-04","06-04")
    Last_day <- c(4,3,1,1,0)
    Data1 <- data.frame(Date,Last_day)
    Data1$index <- c(1:nrow(Data1))
    
    matri <- apply(Data1, 1, function(item){
      start_zero_num <- as.numeric(item[[3]])-1
      one_num <- as.numeric(item[[2]])
      end_zero_num <- nrow(Data1) - start_zero_num - one_num
      if(end_zero_num<0){end_zero_num <- 0}
      vect <- c(rep(0, start_zero_num), rep(1, one_num), rep(0, end_zero_num))[1:nrow(Data1)]
      return(vect)
    })
    
    Data1$Count_day <- apply(matri, 1, sum)

    大概写了下,细节自己完善吧!

    这种还是很简单的,多练习吧,实在不行用for循环也可以,自己用,慢又无所谓。

    在2楼我理解有点偏差答案写错了,不过重新用lubridate来一发:

    核心是使用date+ duration构建完整的合集,比如06-01持续4天就生成06-01到06-04

    这样完整的时间合集就可以table统计频次了。
    另外好处就是跨月份的话问题也不大,不同月份天数不一样什么的细节问题要处理好的话还是建议用专门处理时间序列的包来做。

    library(lubridate)
    
    get_series = function(start, duration){
      start= lubridate::as_datetime(start, format="%m-%d")
      end = start + days(duration-1)
      if(start<=end){
        return(seq(start, end, by="1 day"))
      }
      else{
        return(NULL)
      }
      
    }
    
    Date <- c("06-01","06-02","06-03","06-04","06-04")
    Last_day <- c(4,3,1,1,0)
    Data1 <- data.frame(Date,Last_day, stringsAsFactors=FALSE)
    
    rslt = lapply(1:nrow(Data1), function(i){
      rslt = get_series(Data1$Date[i], Data1$Last_day[i])
      rslt=as.character(rslt)
      return(rslt)
    })
    
    table(unlist(rslt))
    #> 
    #> 2019-06-01 2019-06-02 2019-06-03 2019-06-04 
    #>          1          2          3          3

    CMCai0104
    我尝试了如下代码

    Row1_1 <- matrix(0,nrow=95,ncol=95)
    for (i in 1:95){
      k <-  Row[1,i]
      p <- i+k-1
      if (k==0){
        Row1_1[i,] <- 0
        }
        else{
          if (p<=95){
            Row1_1[i,i:p] <- 1
          }
          else{
            Row1_1[i,i:95] <- 1
          }
        }
      }

    但是出现了这个错误
    Error in i:p : NA/NaN argument
    就不知道那里不对。
    Row是1*95的时间序列数据

      代码有问题,大概写一下,大神帮忙完善吧

      library(lubridate)
      library(tidyverse)
      date = c("2019-06-01", "2019-06-02","2019-06-03","2019-06-04","2019-06-04")
      last_day = c(4,3,1,1,0)
      df = data.frame(date, last_day)
      df$date  = ymd(df$date)
      
      for (i in 1:length(df) {
        result <- 
          ifelse(df$last_day[i] > 1, df$date[i] + seq(0:(df$last_day[i] - 1)),
                 ifelse(df$last_day[i] == 1, df$date[i], NULL
                        )
                 )
        print(result)
      }
      table(result)

        如果我没理解错的话,这不就是个 seq + mapply + table 的问题嘛……

        # 构建数据:
        date_df <- data.frame(start = c("06-01","06-02","06-03","06-04","06-04"), 
                              duration = c(4,3,1,1,0))
        # 识别日期:
        date_df$ystart <- as.Date(paste0('2019-', date_df$start))
        # 生成所有日期:
        date_ls <- mapply(function(x1, x2) format(seq(from = x1, length.out = x2, by = 1), '%m-%d'), 
                          date_df$ystart, date_df$duration)
        # 统计频次:
        table(unlist(date_ls))
          2 年 后

          过来擦个屁股 。

          Date <- c("06-01", "06-02", "06-03", "06-04", "06-04")
          Last_day <- c(4, 3, 1, 1, 0)
          Data1 <- data.frame(Date, Last_day)
          
          library(tidyverse)
          library(lubridate)
          Data1 %>% 
            mutate(
              Date = ymd(str_c("2021", Date)),
              reps = map2(
                Date, 
                Last_day,
                ~ seq(.x, by = 1, length.out = .y)          
              )
            ) %>% 
            unnest(reps) %>% 
            count(reps)