首页 > 解决方案 > 自动记录数据和新列

问题描述

我有一个包含每天销售的产品数量的数据集。然而,数据是以一种奇怪的方式记录的。因此,如果售出的商品数量超过 100,则重置记录器并且售出的商品数量从零开始。我提供了一个记录器如何工作的示例。

df <- data.frame(date = c("2020-01-01", "2020-01-02", "2020-01-03", "2020-01-04", "2020-01-05"),
items_sold = c(10,40,90, 10, 20), items_sold_real = c(10,40,90, 110, 130), items_sold_differene_day = c(NA, 30, 50, 20, 20)
)

所以,我正在尝试创建一个看起来像变量 items_sold_real 的新变量。我想知道您是否知道这里有什么好的解决方案。

谢谢,

标签: rcalculated-columns

解决方案


逻辑

  • i如果当天售出的商品数量低于 ,我们检测到已售出的商品已重置i-1。(请注意,只有当每天的销售数量最多可以达到 99 个单位时,这才是正确的)。
  • 如果我们仍然没有超过 100,那么我们只是把出售的物品。
  • 如果我们超过 100,我们必须将售出物品的累计总和乘以 100 乘以我们超过 100 的次数。

代码

  • items_sold < lag(items_sold, default=F)一个值是否低于前一个值的逻辑。
  • cumsum得到这个逻辑向量的累积和(TRUE=1,FALSE=0)。
  • 我们按这个新变量 ( id) 进行分组,以确保cumsum仅应用于同一组的元素。
  • 应用上面提到的公式( id > 0 ) * cumsum(items_sold) + id * 100 + items_sold * ( id == 0 ):如果id > 0加上cumsum100 乘以id,如果不把 的值item_sold
  • 可以使用diff函数计算差异。
library(tidyverse)

#### if you're tagged data.frame is wrong
## basically there is no longer a need for the cumsums
## so no need to group thus we drop the id column and directly
df %>%
 mutate(items_sold_real= cumsum(items_sold<lag(items_sold, default=F))*100 + items_sold, items_sold_differene_day= c(NA,diff(items_sold_real))) -> df

#### if you want to have a result just like the tagged data.frame
df %>%
 mutate(id = cumsum(items_sold < lag(items_sold, default=F))) %>%
 group_by(id) %>%
 mutate(items_sold_real= ( id > 0 ) * cumsum(items_sold) + id * 100 + items_sold * ( id == 0 ) ) %>% 
 ungroup %>% select(-id) %>%
  mutate(items_sold_differene_day= c(NA, diff(items_sold_real))) -> df
identical(df, tibble(df.result))
#> TRUE
df
# A tibble: 5 x 4
  date       items_sold items_sold_real items_sold_differene_day
  <fct>           <dbl>           <dbl>                    <dbl>
1 2020-01-01         10              10                       NA
2 2020-01-02         40              40                       30
3 2020-01-03         90              90                       50
4 2020-01-04         10             110                       20
5 2020-01-05         20             130                       20

数据

df <- data.frame(date = c("2020-01-01", "2020-01-02", "2020-01-03", "2020-01-04", "2020-01-05"),
 items_sold = c(10,40,90, 10, 20))

df.result <- data.frame(date = c("2020-01-01", "2020-01-02", "2020-01-03", "2020-01-04", "2020-01-05"), 
 items_sold = c(10,40,90, 10, 20),
 items_sold_real = c(10,40,90, 110, 130),
 items_sold_differene_day = c(NA, 30, 50, 20, 20)
)

推荐阅读