【问题标题】:Is there a way to calculate ratio between a crosstab dataframe with another dataframe in pandas?有没有办法计算交叉表数据框与熊猫中另一个数据框之间的比率?
【发布时间】:2022-01-07 14:59:52
【问题描述】:

总结 - 最终目标是根据 Pandas 中交叉表函数的输出与共享索引处的另一个数据框计算百分比。

我尝试过的 - 尝试将原始交叉表数据框拆分为分子和 div 另一个数据框,但它似乎并没有那样工作,因为结果都是 nan

代码

import pandas as pd
import numpy as np 

df1 = pd.DataFrame({"Vntg": ["2020-01","2020-02","2020-03"],"Funded":[1000,2000,4000]}) # This is the df we want to use as denominator
df2 = pd.DataFrame({"Vntg": ["2020-01","2020-01","2020-01","2020-02","2020-02","2020-03"],
                    "Funded":[1000,1000,1000,2000,2000,4000],
                    "Payment":[10,20,20,30,15,30],
                    "Timing":[0,1,2,0,1,0]})
ct_df = pd.crosstab(df2["Vntg"], df2["Timing"], values=df2["Payment"], aggfunc="sum", margins=False)
ct_df = ct_df.cumsum(axis=1) # This is the crosstab df we want to use as numerator on a cumulative basis

cumsum 开始累积付款,有没有办法将df1 中的资金金额转换/替换为百分比?在此先感谢并感谢所有帮助。

我还查看了下面的帖子,但它似乎没有解决我的问题: Customized normalization of pd.crosstab()

编辑:

所以我认为有些人对这个问题感到困惑。澄清一下,最终结果将是在时间 0 时从 df2 中取出 10,然后除以资助金额,即 2020-01 年份从 df1 中取出 1000。对于随后在 1 的时间,它只是来自df2 的 (10+30),并为同一年份从df1 分配了相同的资金数额,因为它本质上没有改变。结果将由其他年份的相同逻辑填充。

【问题讨论】:

  • 嗨 limasuma - 我对两个数据框中各个列的含义有些困惑,尤其是 df2 中的“付款”和“时间”。当您说“以百分比形式将df1 中的资金金额转换/替换为美元价值”时,将列除以其总数是否合适?
  • @DaveB 是的,这是我最初的想法,只需将资金列划分为df1,但它似乎并没有解决我的问题,因为它返回所有nan

标签: python python-3.x pandas dataframe crosstab


【解决方案1】:

下面的方法不使用crosstab,但应该给出相同的答案(IIUC):

(
    df2.sort_values(["Vntg", "Timing"])
    .assign(cum_paymt=lambda df: df.groupby("Timing")["Payment"].transform("cumsum"))
    .assign(cum_share=lambda df: df["cum_paymt"] / df["Funded"])
    .pivot(index="Vntg", columns="Timing", values="cum_share")
)

【讨论】:

  • 感谢您的回答。我可以看到它是如何工作的并且非常接近。澄清一下,最终结果将是时间 0,2020-01 年份的资助金额为 10/1000,时间 1 的资助金额为 (10+30)/1000。该资助金额不会改变,它必须来自df1 因为在 df2 中的资助由于重复而膨胀。
  • 嗯,我不确定我是否理解正确。 “资助”列不受重复项的影响,对吧?
  • df2 中的“funded”列确实如此,因为它会根据年份从df1 简单匹配。例如,如果我们查看 df2,则 2020-01 的资助是 1000 而不是 3000。我还做了一些修改,如果有意义,请告诉我。
【解决方案2】:

如果你以dataframe的形式给出预期的输出,对大家来说会更容易:

>>> ct_df.cumsum(axis=1).div(df1.set_index('Vntg')['Funded'], axis=0).mul(100)
Timing      0     1    2
Vntg                    
2020-01  1.00  3.00  5.0
2020-02  1.50  2.25  NaN
2020-03  0.75   NaN  NaN

【讨论】:

    猜你喜欢
    • 2021-12-30
    • 1970-01-01
    • 2016-05-20
    • 1970-01-01
    • 2019-06-05
    • 1970-01-01
    • 2022-01-23
    • 1970-01-01
    • 2018-03-28
    相关资源
    最近更新 更多