【问题标题】:R - Sum within group and only if another variable has consecutive valuesR - 组内求和,并且仅当另一个变量具有连续值时
【发布时间】:2019-07-20 06:18:28
【问题描述】:

我有一个数据框,其中每一行都是特定月份的公司。我有两列:金额和交易次数。我需要按三个月确定那些在金额列中至少有 150.0 且在交易数列中至少有 11 的公司。我有大约 50 个月的观察时间。

在Stata中,我所做的是将数据按id和月份排序,然后询问三个月的总和是否高于条件。这是我通过使用 Stata 的 [_n] 功能完成的:对数据进行排序并在观察 [_n] 中,我知道观察 [_n-1] 是上个月的同一家公司:

by id: replace auxactivado = 1 if auxactivado != 1 & !missing(amount) & ///
(amount[_n] + amount[_n-1]) > 150.00 & !missing(transac) & ///
(transac[_n] + transac[_n-1]) >= 10 & (mes[_n] == (mes[_n-1] + 1) | mes[_n] == 1 & mes[_n-1] == 12 & ao[_n] != ao[_n-1])

例如,在上面的 Stata 代码中,我检查了两个月内是否满足条件(我还检查了年份的变化;在下面的数据中,我创建了一个辅助月份来对此进行调整,所以不需要这样做调整了)。

我想在 R 中执行此操作,但不知道如何操作。我在网上进行了广泛的研究,但无法提出解决方案。任何想法将不胜感激

month   year   monthaux           id    amount  transac
    2   2019         26      1201857     301.0     7
    3   2019         27      1201857     423.9     9
    4   2019         28      1201857     684.7    10
    5   2019         29      1201857     494.1     6
    4   2018         16      1202268     51       13
    5   2018         17      1202268     80       15
    2   2019         26      1202268     20       53
    6   2017          6      1202545     102.97    6
    7   2017          7      1202545     2429.6    1
    8   2017          8      1202545     1735.0    1

这是我的一部分数据,以防我不清楚。请注意,月份并不总是连续的:我只需要在连续的月份检查条件。

我希望 id 1201857 显示为 1(满足条件),1202268 显示为 0(满足交易但由于非连续月份而不是金额)和 1202545 显示为 0(满足金额,不满足交易条件)

编辑:eastclintw00d 一直在帮助我,这类数据存在一些问题,条件是在两个月内满足。

id  month   year    amount  transac
2068814 9   2016    151.18  5
2068814 10  2016    206.36  7

2037434 8   2018    85.43   1
2037434 10  2018    744.91  4
2037434 11  2018    630.8   6
2037434 1   2019    596.33  3


structure(list(id = c(2068814L, 2068814L, 2037434L, 2037434L, 
2037434L, 2037434L, 2037434L, 2037434L, 2037434L, 2037434L, 2037434L, 
2037434L, 2037434L, 2037434L, 2037434L, 2037434L, 2037434L, 2037434L, 
2037434L, 2037434L, 2037434L, 2037434L), ao = c(2016L, 2016L, 
2017L, 2017L, 2017L, 2017L, 2017L, 2017L, 2018L, 2018L, 2018L, 
2018L, 2018L, 2018L, 2018L, 2018L, 2018L, 2018L, 2019L, 2019L, 
2019L, 2019L), mes = c(9L, 10L, 7L, 8L, 9L, 10L, 11L, 12L, 1L, 
2L, 3L, 4L, 5L, 6L, 7L, 8L, 10L, 11L, 1L, 3L, 4L, 5L), importe_dol = c(151.18, 
206.36, 268.85, 299.97, 63.99, 797.27, 525, 643.15, 108.58, 128.21, 
452.24, 403.25, 92, 1003.45, 158.96, 85.43, 744.91, 630.8, 596.33, 
574.02, 80.50351324, 444.9815415), cant_transac = c(5, 7, 2, 
1, 1, 2, 1, 2, 1, 1, 3, 1, 1, 3, 1, 1, 4, 6, 3, 4, 1, 3)), row.names = c(45L, 
811L, 10507L, 12459L, 15487L, 16601L, 19590L, 22927L, 27284L, 
30505L, 33036L, 36794L, 41810L, 43778L, 49722L, 54720L, 61910L, 
67047L, 77803L, 89001L, 97082L, 100933L), class = "data.frame")

【问题讨论】:

  • 你的意思是,在数据框中添加一列显示ID是否满足条件?条件是.. 1) 每行的金额必须至少为 150 ... 2) 交易必须至少为 11 ... 3) 并且月份必须是连续的??或者您的意思是金额和交易的总和必须满足 ID 的最低要求,并且必须是连续的月份?
  • 对于 id 1202268,有 2342019 月份的行,它们在同一个三个月中并且是连续的。如果我们将这些行的amount 相加,我们得到1413.96,对于这些行大于150, every transaction` 超过11 所以总和超过11。那你为什么说1202268 不满足条件“由于不连续的月份而不是金额”
  • 我也对你的“三个月”定义感到困惑。在您的 Stata 代码中,您似乎总是在检查上个月,无论是否连续,无论数字如何。通常,三个月定义为 1-4、5-8、9-12 个月。这就是你想要的意思吗?
  • 对不起,Gregor,我删除了你提到的关于 1202268 的数据,因为它是错误的,如你所说。奥马尔,我的意思是金额和交易的总和,正如你猜对的那样。
  • 我的意思是三个月连续三个月,实际上,不是第一季度,第二季度,第三季度,第四季度。抱歉不够彻底。

标签: r stata


【解决方案1】:

假设你的表叫df试试:

library(dplyr)
df  %>% 
  group_by(id, year, trimester = ceiling(month / 4)) %>% 
  summarise_at(vars(transac, amount), sum) %>% 
  mutate(criterion = if_else(transac >= 11 & amount >= 150, 1, 0))

鉴于您对三个月的澄清,以下代码应该可以解决问题。我首先创建三个关键变量的笛卡尔积,然后在其上加入您的数据框。我创建相关变量的第一和第二滞后并检查它们是否符合标准。最后,我会筛选出您正在寻找的那些条目。

library(dplyr)
library(tidyr)
crossing(
  data.frame(ao = min(df$ao):max(df$ao)),
  data.frame(mes = 1:12),
  data.frame(id = unique(df$id))
) %>% 
  left_join(df %>% mutate(original = 1), by = c("ao", "mes", "id")) %>% 
  arrange(id, ao, mes) %>% 
  mutate(
    cant_transac2 = if_else(id == lag(id), lag(cant_transac), NA_real_), 
    cant_transac3 = if_else(id == lag(id, 2), lag(cant_transac, 2), NA_real_), 
    importe_dol2 = if_else(id == lag(id), lag(importe_dol), NA_real_), 
    importe_dol3 = if_else(id == lag(id, 2), lag(importe_dol, 2), NA_real_), 
  ) %>% 
  replace_na(list(cant_transac2 = 0, cant_transac3 = 0, importe_dol2 = 0, importe_dol3 = 0)) %>% 
  mutate(criterion = if_else(cant_transac + cant_transac2 + cant_transac3 >= 11 & importe_dol + importe_dol2 + importe_dol3 >= 150, 1, NA_real_)) %>% 
  filter(original == 1) %>% 
  select(-original, -cant_transac2, -cant_transac3, -importe_dol2, -importe_dol3)

【讨论】:

  • 这也是我最好的猜测,但我认为 OP 也想按year 分组...
  • 仅供参考,您可以保存一行并在group_by 中定义trimester。不需要先mutate
  • 谢谢你们。我会尽快尝试(不幸的是现在不是)。如果您允许我滥用您的慷慨,我将如何在我的数据中创建一个包含是否满足条件的列?非常感谢。
  • 嗨。我已经尝试过代码,但正如 Gregor 上面提到的,我并不是指传统意义上的“三个月”。我将三个月定义为连续三个月,即 nov-dec-jan 月份将是一个三个月。很抱歉,我对此一无所知,但您的代码没有考虑到这一点,我不知道如何解决它(实际上实现这是我发布问题时的主要问题)。谢谢。
  • 我发表了一条评论,其中包含一个我已经解决的愚蠢问题。非常感谢,这似乎有效,虽然我还不能完全检查它。我应该如何修改代码以获得与以前相同的数据,但现在将“标准”添加为一列?这样我就可以将它与我拥有的 Stata 代码进行比较,最终解决我所有的问题。您非常有帮助,我将您的答案标记为正确。非常感谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-09-10
  • 1970-01-01
  • 2019-03-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多