【问题标题】:Generate dates based on 2 different ranges根据 2 个不同的范围生成日期
【发布时间】:2019-11-04 13:41:17
【问题描述】:

我有一个带有列的数据框 df:

Date_1  count
01/09/2019  5
02/09/2019  4
03/09/2019  5
04/09/2019  6
05/09/2019  7
06/09/2019  8
07/09/2019  10
08/09/2019  9
09/09/2019  11
10/09/2019  12
11/09/2019  13
12/09/2019  14
13/09/2019  15
14/09/2019  18
15/09/2019  17
16/09/2019  18
17/09/2019  19
18/09/2019  20
19/09/2019  21
20/09/2019  22
21/09/2019  23
22/09/2019  24
23/09/2019  25
24/09/2019  26
25/09/2019  27
26/09/2019  28
27/09/2019  29
28/09/2019  30
29/09/2019  30
30/09/2019  30

我想生成具有 3 列 date_1、count、date_2 的 df2,这样:

date_2 是根据计数生成的。如果 date_1 的计数为 5,则数据框中将有 5 个条目。 date_2 也有以下约束:

  1. 70% 的值在(date_1 - 10 到 date_1 - 2)的范围内
  2. 剩余值在 (date_1 - 30 到 date_1 - 11) 范围内

date_1 和 date_2 中的每一个都应该是唯一的元组,即没有对 (date_1,date_2) 重复。

例如:

对于第一行: date_1 的 4 个值应在 range1 = (01/09/2019 - 10 = 22/08/2019 至 01/09/2019 - 30/08/2019) 的范围内,其余 1 个值应在 range 范围内2(01/09/2019 - 30 = 02/08/2019 至 01/09/2019 - 21/08/2019)。

对于 count = 30 的数据框中的值,我们不需要进行此更改,因为我们需要唯一值,并且由于 date_2 可以采用的总值是 30,因此我们必须合并所有值。 (在那种情况下,我们不能选择 70% 和 30%)

我无法理解如何根据这些因素特别设计该数据框。因此,对于计数 >11,它应该具有 1 范围内的所有值(8 个值)。在此之前,它是范围 1 和范围 2 中的 70% 和 30% 划分。

谁能帮我定义这些约束。

谢谢

【问题讨论】:

  • 要求date_2的70%的值在(date_1 - 10 to date_1 - 2)的范围内,它们是在某些情况下,独一无二是不可能的。例如。对于 28/09/2019,您需要 30 个输出行。其中 70 % 是 21,可供选择的日期只有 9 个日期。也许在这种情况下应该允许重复?
  • @Valdi_Bo 就像我在问题中提到的那样,在这些情况下,将存在 9 个日期,而其余日期必须在其他日期范围内。就像我提到的,30 是计数的情况,那么我们需要提供 1 个月的范围。在任何情况下,我们都不需要对 date_1、date_2 进行重复

标签: python pandas numpy


【解决方案1】:

要定义的第一个函数是:

def getSample(rng, n):
    siz = rng.size
    return rng.sample(n = n, replace = n > siz)

它从 rng 返回一个 n 个元素的样本。 如果可能(所需的元素数量小于或等于 到 rng 中的元素数量)样本没有重复。

第二个功能是:

def getDates(dat, n):
    td1d = pd.Timedelta(1, 'D')
    # Date ranges
    rng1 = pd.Series(pd.date_range(dat - td1d * 30, dat - td1d * 11, freq='D'))
    rng2 = pd.Series(pd.date_range(dat - td1d * 10, dat - td1d * 2, freq='D'))
    # Numbers of dates
    n2 = int(round(n * 0.7))
    n1 = n - n2
    return pd.concat([getSample(rng1, n1), getSample(rng2, n2)])\
        .sort_values().reset_index(drop=True)

它:

  • 同时生成日期范围 [d-30:d-11][d-10:d-2]
  • 计算要从每个范围中获取的两个元素的数量。
  • 从两个范围(所需大小)中获取样本,将它们连接起来, 排序并返回结果。

最后一个函数,为当前行生成“复制行”,是:

def repl(row):
    dat = row.Date_1
    cnt = row['count']
    return pd.DataFrame({'date_1': dat, 'count': cnt, 'date_2': getDates(dat, cnt)})

现在要做的最后一件事是应用此函数并连接结果:

df2 = pd.concat(df1.sort_values('Date_1').\
    apply(repl, axis=1).tolist(), ignore_index=True)

注意:如果 [d-10:d-2] 范围内的日期数超过 可用日期数,这些日期重复。

21:48:25Z 开始编辑以下评论

你的构想失败了:举个例子2019-09-28 行(需要 30 行)。 从 [d-10 : d-2] 范围内应该取 21 个日期。

但是因为那里只有 9 个日期,那么:

  • 我们只能从这个范围内取 9
  • 所以剩余的 21 日期应该取自第二个范围 ([d-30 : d-11])。

但是这个范围只包含20个日期,所以无法取 21 日期从那里开始(没有重复)。

结论:你的要求被夸大了。

再说一句:

实际上这个任务是不可能的事实可以从表格中看出 以下观察:

日期范围 [d-30 : d-2] 包含 29 个日期。 所以不要指望从这个池中可以采取 30 个不同的日期,无论两个子范围之间的划分如何。

【讨论】:

  • @Valdo_Bo 谢谢你的回答,但是,我不明白为什么日期是重复的?
  • 记录日期 28/09/2019。总共应该有 30 个日期,即:范围 [d-10 : d-2] 中的 21 个。但是这个范围只包含 9 个日期,因此不可能创建一个没有重复的 21 个日期的样本。
  • 在这种情况下,我们选择 range1 中的所有值,然后从 range_2 中提取值。
  • 你检查了吗?
  • 但是这样你就违反了 70 % 行应该有 [d-10 : d-2] 的 date_2 的原则 范围。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-23
  • 2019-08-25
  • 1970-01-01
  • 2016-12-10
  • 1970-01-01
相关资源
最近更新 更多