【问题标题】:randomly split dataframe into groups with even distribution of values将数据帧随机分成具有均匀分布值的组
【发布时间】:2020-12-12 15:54:32
【问题描述】:

我有两个组(AB)的数据框,在这些组中,有 6 个子组(abcde 和 @987654329 @)。下面的示例数据:

index   group    subgroup    value
0       A        a           1
1       A        b           1
2       A        c           1
3       A        d           1
4       A        e           1
5       A        f           1
6       B        a           1
7       B        b           1
8       B        c           1
9       B        d           1
10      B        e           1
11      B        f           1
...     ...      ...         ...

虽然我在这里只列出了 12 行等于 1 的值,但实际上在实际数据集中有 300 行(值等于 2、3 等)。我正在尝试将数据框随机拆分为 6 批 50 个值。但是,我希望每个批次都包含均匀分布的 group 值(即 25 个 A 和 25 个 B)以及大致均匀分布的 subgroup 值。

例如,batch_1 可能包含:

25 个A,其中包含 4 个a、5 个b、4 个c、4 个d、5 个e 和3 个f的。以及 25 个B,其中包含 5 个a、4 个b、3 个c、5 个d、4 个e 和4 个f .

这 6 个批次将提供给 1 个用户。 (所以我实际上需要将数据帧随机拆分为多个 不同 6 个批次以供更多用户使用。)但我不知道这是应该随机拆分数据帧还是从中采样的问题。有人对如何实现这一点有建议吗?

这可能会有所帮助,但不能确保值的均匀分布:https://www.geeksforgeeks.org/break-list-chunks-size-n-python/

【问题讨论】:

  • 可以尝试按组列分组,然后使用样本获取随机样本,对子组重复相同的操作

标签: python pandas dataframe data-wrangling


【解决方案1】:

使用一些技巧

  1. 使用pd.factorize() 将分类数据转换为每个类别的值
  2. 计算代表组/子组配对的值/因子f
  3. 将其随机化一点np.random.uniform(),最小值和最大值接近 1
  4. 一旦有了代表分组的值,sort_values()reset_index() 就可以有一个干净的有序索引
  5. 最终按整数余数分组
group = list("ABCD")
subgroup = list("abcdef")
df = pd.DataFrame([{"group":group[random.randint(0,len(group)-1)], 
 "subgroup":subgroup[random.randint(0,len(subgroup)-1)],
 "value":random.randint(1,3)} for i in range(300)])

bins=6
dfc = df.assign(
    # take into account concentration of group and subgroup
    # randomise a bit....
    f = ((pd.factorize(df["group"])[0] +1)*10 + 
            (pd.factorize(df["subgroup"])[0] +1) 
            *np.random.uniform(0.99,1.01,len(df))
        ),
).sort_values("f").reset_index(drop=True).assign(
    gc=lambda dfa: dfa.index%(bins)
).drop(columns="f")

# check distribution ... used plot for SO
dfc.groupby(["gc","group","subgroup"]).count().unstack(0).plot(kind="barh")
# every group same size...
# dfc.groupby("gc").count()

# now it's easy to get each of the cuts.... 0 through 5
# dfcut0 = dfc.query("gc==0").drop(columns="gc").copy().reset_index(drop=True)
# dfcut0

输出

【讨论】:

  • 非常感谢!分步说明中的详细程度非常有帮助。您能解释一下为什么在gc=lambda dfa: dfa.index%(bins) 中使用整数余数吗?
  • 这是一个简单的案例,就是将它放入 6 个垃圾箱之一。所以必须有一个整数和一个余数。即逐行分配给其中一个垃圾箱,不是靠近垃圾箱而是垃圾箱
  • 我可以在您的帖子上再次征求您的意见吗?我现在正在尝试执行完全相反的任务,即将我的数据框拆分为 50 个箱,以便每个箱包含 6 个唯一值。每个批次应包含子组值的均匀分布和组值的大致均匀分布。但是,在代码中切换 groupsubgroup 不会随机将组值分成相等的数量。你有什么建议吗? (如果我应该提出一个新问题,请告诉我!我很乐意这样做,但这个问题似乎与原帖重复。)
  • @psychcoder 注意f 的计算偏向于对子组进行分组(乘以 10)。调整f 的计算应该达到你想要的(子组作为驱动程序)
猜你喜欢
  • 1970-01-01
  • 2014-02-04
  • 2017-07-16
  • 1970-01-01
  • 1970-01-01
  • 2011-08-08
  • 1970-01-01
  • 1970-01-01
  • 2011-08-23
相关资源
最近更新 更多