【问题标题】:Element-wise division with accumulated numbers in Python?Python中累积数字的元素除法?
【发布时间】:2020-02-13 00:55:47
【问题描述】:

标题可能会让人感到困惑(老实说,不太清楚如何用一句话来概括它),所以这里有一个更好的解释:

我目前正在处理一个关于不同属性的数据帧A,并且我在数据列age 上使用了.groupby[].count() 函数来创建一个事件列表:

A_sub = A.groupby(['age'])['age'].count()

A_sub返回一个类似下面的Series(值是随机修改的):

age
1    316
2    249
3    221
4    219
5    262
...
59    1
61    2
65    1
70    1
80    1
Name: age, dtype: int64

我想绘制一个按元素划分的值列表。我要执行的除法是元素值除以索引大于或等于该元素的所有元素的总和。换句话说,例如,对于 3 岁,它应该返回

221/(221+219+262+...+1+2+1+1+1)

相同的计算应该适用于所有元素。理想情况下,结果应该是相似的类型/格式,以便可以绘制。

【问题讨论】:

  • 我不太习惯 pandas 和 series,但是在相当接近的 numpy 中,您可以从计算要除以每个元素的系数的向量开始,然后除以元素- 用这些系数来计算你的年龄。
  • 嗨@Mathieu你介意稍微演示一下这个过程吗?不太确定我是否遵循,因为我不太习惯在 numpy 中这样做。

标签: python pandas numpy numpy-ndarray


【解决方案1】:

这是一个使用 numpy 的简单示例。类似的方法可以用于 pandas。 for 循环很可能会被更智能、更高效地计算系数的方法所取代。

import numpy as np

ages = np.asarray([316, 249, 221, 219, 262])
coefficients = np.zeros(ages.shape)

for k, a in enumerate(ages):
    coefficients[k] = sum(ages[k:])

output = ages / coefficients

输出:

array([0.24940805, 0.26182965, 0.31481481, 0.45530146, 1.        ])

编辑:0for 循环处的系数初始化可以替换为:

coefficients = np.flip(np.cumsum(np.flip(ages)))

【讨论】:

  • 谢谢马修!我可能会做的只是np.asarray(A_sub)。我的一个担忧是,这种方法忽略了没有价值的年龄(例如,60 岁将从数组中跳过)。是否可以有没有价值的年龄值为0?因此,像 60、62、63、64、66、... 这样的年龄都将具有 0 的数值,因此会影响结果(就元素数量而言)。
  • @Robin 当然可以,但是你想如何考虑年龄为 0?带他们出去?目前,它与您在帖子中描述的完全一样。您能否举一个 [316, 249, 221, 219, 0, 262, 0] 的预期输出示例(0 表示 5 和 7)。
【解决方案2】:

您可以使用 pandas 中的函数cumsum() 来获取累计和:

A_sub = A['age'].value_counts().sort_index(ascending=False)
(A_sub / A_sub.cumsum()).iloc[::-1]

【讨论】:

    【解决方案3】:

    没有理由使用 numpy,pandas 已经包含了我们需要的一切。

    A_sub 似乎返回了一个系列,其中age 是索引。这并不理想,但应该没问题。因此,下面的代码在一系列上运行,但可以很容易地修改为使用 DataFrame。

    import pandas as pd
    
    s = pd.Series(data=np.random.randint(low=1, high=10, size=10), index=[0, 1, 3, 4, 5, 8, 9, 10, 11, 13], name="age")
    print(s)
    
    res = s / s[::-1].cumsum()[::-1]
    res = res.rename("cumsum div")
    

    我看到了您对索引中缺少年龄的评论。以下是如何添加从 min 到 max 索引范围内的缺失索引,然后执行除法。

    import pandas as pd
    
    s = pd.Series(data=np.random.randint(low=1, high=10, size=10), index=[0, 1, 3, 4, 5, 8, 9, 10, 11, 13], name="age")
    
    s_all_idx = s.reindex(index=range(s.index.min(), s.index.max() + 1), fill_value=0)
    print(s_all_idx)
    
    res = s_all_idx / s_all_idx[::-1].cumsum()[::-1]
    res = res.rename("all idx cumsum div")
    

    【讨论】:

    • 如果您对其他答案投反对票,请在 cmets 中解释,以便我们改进我们的解决方案。在您发布答案的同时,我得到了反对。 @Mathieu 你怎么了?
    • 对不起,我忘记发表评论解释了!我对您的答案投了反对票,因为它似乎没有产生正确的输出。既然你已经提到了,我很好奇为什么我的回答被否决了。
    • @MykolaZotko 也得到了一个,不知道是不是同时,但仍然没有评论:(
    猜你喜欢
    • 1970-01-01
    • 2015-11-27
    • 2013-02-25
    • 2017-05-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-03
    相关资源
    最近更新 更多