【问题标题】:R: Creating new dataframe based on multiple conditions on existing dataframeR:根据现有数据框的多个条件创建新数据框
【发布时间】:2019-04-25 19:37:13
【问题描述】:

我需要在现有数据帧上使用多个条件创建一个新数据帧。

我尝试使用 dplyr 函数,特别是针对多个条件进行总结,但由于应用条件后数据集大小减小,因此失败了。

为了解释,下面是我想要实现的一个简单示例。

df <- data.frame(User = c("Newton","Newton","Newton","Newton","Newton"),
                 Location = c("A","A","B","A","B"),
                 Movement = c(10,10,20,20,30),
                 Unit = c(-2,2,2,-2,-1),
                 Time = c("4-20-2019","4-20-2019","4-21-2019","4-21-2019"
                          ,"4-23-2019"))

dfNew <- data.frame(User = c("Newton","Newton","Newton"),
                    FromLocation = c("A","A","B"),
                    ToLocation = c("A","B","B"),
                    Movement = c(10,20,30),
                    Units = c(2,2,-1))

dfNew的计算条件如下:

  1. 看df的第一行: a) 如果移动为 10 且单位为负 - 忽略此行

  2. 看df的第二行: a) 如果移动为 10 且单位为正 - FromLocation 和 ToLocation 均为 A,且 Units 取自 df,即 2

  3. 看df的第三行: a) 如果移动为 20 且单位为正 - ToLocation (B) 和 Units (2) 必须取自这一行,FromLocation 必须取自下一行

  4. 看df的第四行: a) 如果移动为 20 且单位为负 - dfnew 上一行的 FromLocation(A) 必须取自该行

  5. 看df的第五行: a) 如果移动类型为 30,则 ToLocation 和 FromLocation 都将为 B,单位将与 df 相同,即 -1

另一种可能有用的模式是每个动作都将在同一天/同一时间发生。另请注意,该示例仅适用于 1 个用户,我有超过 2000 个必须应用类似条件的用户。

就像我说的那样,我尝试使用 dplyr 并汇总所有这些条件,但由于数据集的大小不同,我可以找到一种方法来使其工作。

感谢任何建议,谢谢!

【问题讨论】:

    标签: r dataframe dplyr


    【解决方案1】:

    听起来dplyr::group_bycase_when 可能就足够了,但我不确定这些是对您的桌子“规则”的正确解释。

    library(dplyr)
    df %>%
      group_by(User) %>%
      mutate(FromLocation = case_when(Movement == 10 & Unit < 0 ~  "DROP",
                                      Movement == 10 & Unit > 0 ~  Location,
                                      Movement == 20 & Unit < 0 ~  lag(Location),
                                      Movement == 20 & Unit > 0 ~  lead(Location),
                                      Movement == 30  ~ "B",
                                      TRUE   ~ "not specified in rules"),
    
             ToLocation = case_when(Movement == 10 & Unit < 0 ~  "DROP",
                                    Movement == 10 & Unit > 0 ~  Location,
                                    Movement == 20 & Unit < 0 ~  lag(Location), # Not given 
                                    Movement == 20 & Unit > 0 ~  Location,
                                    Movement == 30  ~ "B",
                                    TRUE   ~ "not specified in rules")) %>%
      ungroup() %>%
      filter(FromLocation != "DROP") %>%
      select(User, FromLocation, ToLocation, Movement, Unit)
    

    结果

    # A tibble: 4 x 5
      User   FromLocation ToLocation Movement  Unit
      <chr>  <chr>        <chr>         <dbl> <dbl>
    1 Newton A            A                10     2
    2 Newton A            B                20     2
    3 Newton B            B                20    -2
    4 Newton B            B                30    -1
    

    【讨论】:

    • 谢谢,@Jon Spring。这完成了工作!在这种程度上使用 dplyr 为我开辟了更多可能性
    猜你喜欢
    • 2022-01-18
    • 2023-03-21
    • 1970-01-01
    • 2021-11-04
    • 2018-07-01
    • 2017-03-20
    • 2021-12-09
    • 2021-02-08
    • 2020-07-09
    相关资源
    最近更新 更多