【问题标题】:Divide amount over rows将金额除以行
【发布时间】:2020-01-17 14:03:50
【问题描述】:

我想将一定数量的项目分成多行。每行应该至少获得 1 个,其余的根据他们所需的份额,直到所有项目都分发完毕。 假设我们有 6 个可用,我想得到如下结果。

使用max(1, factor * available) 并不一定等于可用项目的总数。

有办法吗? 我在 spark 环境中有数据,所以最酷的方法是 pyspark 甚至是 pandas/numpy 解决方案。 显然,它可以很容易地在 python 循环中完成。

输入: 共有 6 个

+---+-------------+
| c1|       factor|
+---+-------------+
|  A|        0.001|
|  B|          0.2|
|  C|          0.2|
|  D|          0.2|
|  E|          0.3|
+---+-------------+

预期输出:

+---+-------------+---------+
| c1|       factor|   result|
+---+-------------+---------+
|  A|        0.001|        1|
|  B|          0.2|        1|
|  C|          0.2|        1|
|  D|          0.2|        1|
|  E|          0.3|        2|
+---+-------------+---------+

【问题讨论】:

  • 为什么说它行不通?输入应该是用户输入吗?或者它来自哪里?简单地定义列不起作用? df['factor'] = max(1,df['factor'] * available)available = int(input('available = '))。您可以重新调整 factor 使其总和 1 从而确保您的 available 得到完全分布并与 factor 值成比例。

标签: python pandas numpy pyspark


【解决方案1】:

如果我理解正确,这就是我处理问题的方式:

import numpy as np
import pandas as pd 

data = {'c1':['A','B','C','D','E'],'factor':[0.001,0.2,0.2,0.2,0.3]}
df = pd.DataFrame(data)
df['factor_rescaled'] = df['factor'] / df['factor'].sum()
available = int(input('Available = '))
df['result'] = np.where(round(df['factor_rescaled']*available,0) < 1,1,round(df['factor_rescaled']*available,0))
print(df)

传递值 6 会产生以下结果:

  c1  factor  factor_rescaled  result
0  A   0.001         0.001110     1.0
1  B   0.200         0.221976     1.0
2  C   0.200         0.221976     1.0
3  D   0.200         0.221976     1.0
4  E   0.300         0.332963     2.0

重新调整是为了确保如果因子太高或太低,available 值是完全分布的,没有过度/不足分布。最后我不确定这个available 数字来自哪里,所以我只是将它作为输入,例如6

最终编辑:使用 np.where 因为Why is np.where faster than pd.apply

【讨论】:

    【解决方案2】:

    你可以使用 pandas 做到这一点:

    >>> df
      c1  factor
    0  A   0.001
    1  B   0.200
    2  C   0.200
    3  D   0.200
    4  E   0.300
    >>> available, s = 6, df.factor.sum()
    >>> df['result'] = df.factor.apply(lambda x: round(max(1, (x/s)*available)))
    >>> df
      c1  factor  result
    0  A   0.001     1.0
    1  B   0.200     1.0
    2  C   0.200     1.0
    3  D   0.200     1.0
    4  E   0.300     2.0
    

    【讨论】:

    • 这个问题是因子不和 1,所以如果你使用 available = 1000 那么它不会得到完全分布。 df['result'].sum() 将是 901 而不是 1000,因为它应该是。
    • @CeliusStingher 感谢您提到这个问题。我修改了解决方案。
    猜你喜欢
    • 2011-01-03
    • 1970-01-01
    • 2018-05-17
    • 2011-11-15
    • 1970-01-01
    • 2021-12-08
    • 2022-06-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多