R:根据现有数据框上的多个条件创建新数据框

时间:2019-04-25 19:37:14

标签: r dataframe dplyr

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

我尝试使用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,并且单位取自df为2

  3. 查看df的第三行: a)如果移动为20并且单位为正-ToLocation(B)和Unit(2)必须从此行中获取,而FromLocation必须从下一行中获取

  4. 查看df的第四行: a)如果移动为20并且单位为负-dfnew的前一行的FromLocation(A)必须从此行

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

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

就像我说的那样,我尝试使用dplyr进行总结并总结了所有这些条件,但是由于数据集的大小不同,因此我找到了一种使之起作用的方法。

感谢任何建议,谢谢!

1 个答案:

答案 0 :(得分:1)

听起来class Foo { constexpr static bool useVersionA = /* stuff */; using store_t = typename std::conditional<useVersionA, store_A, store_B>::type; }; dplyr::group_by可能就足够了,但是我不确定这些表对表的“规则”是否正确。

case_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)