【问题标题】:Apply cumsum function to a variable with several conditions将 cumsum 函数应用于具有多个条件的变量
【发布时间】:2021-04-21 18:14:10
【问题描述】:

我有类似的数据:

data <- data.frame (date=seq.Date(as.Date("2021-03-21"),as.Date("2021-04-21"),"day"),
                    rad= sample(1:10,32, replace = T))

> head(data)
        date rad
1 2021-03-21   1
2 2021-03-22   5
3 2021-03-23   1
4 2021-03-24   9
5 2021-03-25  10
6 2021-03-26   4
...

我目前正在学习扭曲和操作大型数据集,但偶然发现我的 R 知识/谷歌搜索技能不再有帮助。

我想学习两件事:

  1. 如何为某个时期的变量赋值。例如,我想在 2021-04-01 和 2021-04-05 之间的时间段内为 rad 列中的所有元素赋予 42 的值。

  2. 更重要的是(与 1. 无关)我想创建一个代码:

  • 根据“rad”变量创建一个新列
  • 计算某个时间段(例如 2021-04-01 - 2021-04-05)“rad”的累积和
  • 然后取 cumsum 的最后一个值(累计求和周期的总和)并分配给某个时间段(例如 2021-04-06 - 2021-04-15)
  • 对于未应用函数的其余日期,新变量与“rad”变量具有相同的值

如果您需要更好的解释,请告诉我。我根本不知道如何向您展示所需的输出,因为如果我知道,那么我就不会在这里问了。提前谢谢你

最好, 佐林

【问题讨论】:

    标签: r dataframe cumsum


    【解决方案1】:

    您可以使用布尔向量来指定要修改的行:

    data <- data.frame(date=seq.Date(as.Date("2021-03-21"),as.Date("2021-04-21"),"day"),
                        rad= sample(1:10,32, replace = T))
    
    # Specify rows to be modified
    modified <- data$date>=as.Date('2021-04-01') & data$date<=as.Date('2021-04-05')
    modified.after <- data$date>as.Date('2021-04-06') & data$date<=as.Date('2021-04-15')
    
    # First question
    # data$rad[modified] <- 42
    
    # Second question
    data$radnew <- data$rad
    cs <- cumsum(data$rad[modified])
    
    data$radnew[modified] <- cs
    data$radnew[modified.after] <- tail(cs,1) 
    data
    

    【讨论】:

    • 也许data$date&gt;as.Date('2021-04-06')&amp;data$date&gt;as.Date('2021-04-15') 应该是data$date&gt;=as.Date('2021-04-06')&amp;data$date&lt;=as.Date('2021-04-15'),将第二项的比较颠倒过来,包括极端情况。
    • 非常感谢。这正是我正在寻找的。还要感谢@JonSpring 的更正,我也注意到了 :)) 你们摇滚
    【解决方案2】:

    针对您的第一个问题,在base R 中,您可以在提到的日期期间对data 进行子集化,并将该期间的值42 分配到一个新变量中,例如x

    data$rad[data$date >= "2021-04-01" & data$date <= "2021-04-05"] <- 42
    

    您可以使用dplyr 实现同样的目的:

    library(dplyr)
    data %>%
      mutate(rad = ifelse(date >= "2021-04-01" & date <= "2021-04-05", 42, NA))
    

    编辑

    至于你的第二个问题(如果我理解正确的话)你可能最好以这种方式使用dplyr

    data %>%
      mutate(
        new1 = ifelse(date >= "2021-04-01" & date <= "2021-04-05", 42, NA),
        cmsm = cumsum(date >= "2021-04-01" & date <= "2021-04-05"),
        new2 = ifelse(date >= "2021-04-06" & date <= "2021-04-15", max(cmsm), rad))
    

    结果:

             date rad new1 cmsm new2
    1  2021-03-21   2   NA    0    2
    2  2021-03-22   7   NA    0    7
    3  2021-03-23   8   NA    0    8
    4  2021-03-24  10   NA    0   10
    5  2021-03-25   3   NA    0    3
    6  2021-03-26   9   NA    0    9
    7  2021-03-27   8   NA    0    8
    8  2021-03-28   7   NA    0    7
    9  2021-03-29   8   NA    0    8
    10 2021-03-30   5   NA    0    5
    11 2021-03-31   1   NA    0    1
    12 2021-04-01   8   42    1    8
    13 2021-04-02   9   42    2    9
    14 2021-04-03   6   42    3    6
    15 2021-04-04   9   42    4    9
    16 2021-04-05   2   42    5    2
    17 2021-04-06   2   NA    5    5
    18 2021-04-07   7   NA    5    5
    19 2021-04-08   9   NA    5    5
    20 2021-04-09   8   NA    5    5
    21 2021-04-10   4   NA    5    5
    22 2021-04-11   3   NA    5    5
    23 2021-04-12   4   NA    5    5
    24 2021-04-13   9   NA    5    5
    25 2021-04-14   9   NA    5    5
    26 2021-04-15   4   NA    5    5
    27 2021-04-16   6   NA    5    6
    28 2021-04-17   5   NA    5    5
    29 2021-04-18   9   NA    5    9
    30 2021-04-19   3   NA    5    3
    31 2021-04-20   8   NA    5    8
    32 2021-04-21   3   NA    5    3
    

    【讨论】:

    • 感谢您的回复。这不是所需的输出,但是,我确信我无法准确地表达我想要的东西。我修改了您的代码以满足我的期望。这就是我要寻找的第一个问题:data$rad[data$date &gt;= "2021-04-01" &amp; data$date &lt;= "2021-04-05"] &lt;- 42 或使用 dplyr:data %&gt;% mutate(rad = ifelse(date &gt;= "2021-04-01" &amp; date &lt;= "2021-04-05", 42, rad))。我不需要 NA,我需要其他日期的原始数据。但是,我想保留原始列并将新输出转移到新列。
    • 然后新建一个列:data %&gt;% mutate(new = ifelse(date &gt;= "2021-04-01" &amp; date &lt;= "2021-04-05", 42, rad))
    • 关于第二个问题,所需的输出是由 Waldi 实现的。我试图调整您的代码,但只取得了部分成功:data %&gt;% mutate(cmsm = cumsum(date &gt;= "2021-04-01" &amp; date &lt;= "2021-04-05")) %&gt;% mutate(cmsm = ifelse(date &gt; "2021-04-15" | date &lt;"2021-04-01", rad, cmsm))。唯一的区别是累积和应计算 2021-04-01 - 2021-04-05 之间的 rad 值,如下所示:4、13、18、22、32 并且应为 2021- 转移全部总和 (32) 04-06 - 2021-04-15
    • 你看到我的更新了吗?它可以满足您的需要吗?
    • 在您的第一个回答中:非常感谢,这很容易在您的第二个回答中:首先,不需要“new1”。正如我在上面的问题中所说,我的第一个和第二个问题是无关的,我只是使用相同的数据集作为示例。其次,不,这不是我要找的。如果我使用您的示例,我需要一个类似“new2”的列,但它应该采用 2021-04-01 - 2021-04-05 之间的 rad 累积总和如下:8、17 (8+9)、23 (17 +6)、32 (23+9)、34 (32+2)。然后从 2021-04-06 到 2021-04-15 它应该取这五天的全部累积总和的值:在这种情况下是 34
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-11-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多