【问题标题】:Random sample by group and filtering on the basis of result按组随机抽样并根据结果过滤
【发布时间】:2018-08-31 14:50:07
【问题描述】:

我有一个由以下代码生成的数据框

l_ids = c(1, 1, 1, 2, 2, 2, 2)
l_months = c(5, 5, 5, 88, 88, 88, 88)
l_calWeek = c(201708, 201709, 201710, 201741, 201742, 201743, 201744)
value = c(5, 6, 3, 99, 100, 1001, 1002)

dat <- setNames(data.frame(cbind(l_ids, l_months, l_calWeek, value)), 
c("ids", "months", "calWeek", "value"))

看起来像这样:

+----+-------+----------+-------+
| Id | Month | Cal Week | Value |
+----+-------+----------+-------+
|  1 |     5 |   201708 |   4.5 |
|  1 |     5 |   201709 |     5 |
| 1  |     5 |   201710 |     6 |
|  2 |    88 |   201741 |    75 |
|  2 |    88 | 201742   |    89 |
| 2  |    88 | 201743   |    90 |
|  2 |    88 |   201744 |    51 |
+----+-------+----------+-------+

我想从每个 id-month 组中随机抽取一个日历周(这些月份不是日历月)。然后我想保留样本月份之前的所有 id-month 组合。

一个示例输出可能是:假设组 id=2 和月=88 的采样输出返回 cal week 201743 和组 id=1 和月=5 的 201709,那么最终输出应该是

+----+-------+----------+-------+
| Id | Month | Cal Week | Value |
+----+-------+----------+-------+
|  1 |     5 |   201708 |   4.5 |
|  1 |     5 |   201709 |     5 |
|  2 |    88 |   201741 |    75 |
|  2 |    88 | 201742   |    89 |
   2  |    88 | 201743   |    90 |

+----+-------+----------+-------+

我尝试使用 dplyr 的 sample_n 函数(它将按 id-month 组为我提供随机日历周,但是我不知道如何获取该日期之前的所有日历周。你能帮我吗?这个。如果可能的话,我想和 dplyr 合作。

如果您需要更多信息,请告诉我。

非常感谢

【问题讨论】:

  • 好的,忘记我刚刚删除的评论。我认为您的问题看起来很有趣,但我们非常感谢一个示例数据框...(您应该知道 :)
  • 作为一个想法。通过抽样,您将获得抽样日历周的向量。现在,您可以使用此向量在原始数据框的 cal week 列中定义最大值,并过滤掉更高(或更低)的最大值。
  • 嗨 Tjebo,谢谢我添加了一些代码。你能解释一下如何在计算周中找到最大值吗?谢谢。此外,数据框有点大(大约 12 000 000 行)。我实际上在创建随机样本(即使用 sample_n)时遇到了一些性能问题。
  • 明确地说,您只想从一个特定的 Cal Week 中采样,并保留此 Cal Week 之前的行中的 id-month 组合?
  • 嗨 Colin,我想在 id-month 组中采样一个日历周,然后将所有日历周保持在采样的下面。

标签: r random dplyr


【解决方案1】:
require(dplyr) 
set.seed(1)     # when sampling please set.seed
sampled <- dat %>% group_by(ids) %>% do(., sample_n(.,1)) 

sampled_day <- sampled$calWeek

dat %>% group_by(ids) %>% 
  mutate(max_day = which(calWeek %in% sampled_day)) %>%
  filter(row_number() <= max_day)

#You can also just filter directly with row_number() <= which(calWeek %in% sampled_day)

# A tibble: 3 x 4
# Groups:   ids [2]
    ids months calWeek  value
  <dbl>  <dbl>   <dbl>  <dbl>
1  1.00   5.00  201708   5.00
2  2.00  88.0   201741  99.0 
3  2.00  88.0   201742 100 

这取决于行顺序!所以一定要先按天安排。不过,你需要考虑关系。我已经编辑了我以前的答案,并简单地用 过滤

【讨论】:

  • 您好 Tjebo,谢谢。我实际上必须对 id 和月份进行分组(因为真实数据框的结构如何,但我认为这并不重要)。此外,我注意到这段代码在我的 1200 万行数据帧上花费了很长时间。我想这是来自抽样,没有什么可以做的?
  • 根据上面的评论,您可能需要考虑数据表?
【解决方案2】:

这应该可以解决问题:

sample_and_get_below <- function(df, when, size){
  res <- filter(df, calWeek == when) %>%
    sample_n(size)
  filter(df, calWeek > when) %>%
    rbind(res, .)
}
sample_and_get_below(dat, 201741, 1)
  ids months calWeek value
1   2     88  201741    99
2   2     88  201742   100
3   2     88  201743  1001
4   2     88  201744  1002

【讨论】:

  • 嗨,谢谢,但这看起来不正确。我希望结果中有两个 id。然后采样将返回例如 id2 和 88 月份的 cal 周 201742,然后我想要对应于 id2 和 88 个月以及 calWeek 201741 和 201742 的行。
  • 抱歉,我很难理解您想要得到的结果。您能否在问题中提供一个示例输出?
猜你喜欢
  • 2013-08-17
  • 2021-10-19
  • 2016-09-06
  • 2020-05-31
  • 2013-07-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多