【问题标题】:How to convert stacked columns with duplicate indices into multiple unique columns with pandas?如何将具有重复索引的堆叠列转换为具有熊猫的多个唯一列?
【发布时间】:2019-10-14 03:50:04
【问题描述】:

我正在使用一个加密货币时间序列数据集,该数据集包含所有不同的货币垂直堆叠。它有日期、货币和价格 3 列。每种货币的日期范围也不同。

>>> df
        Currency  Date    Price
0       0x        2017-08-16  0.111725
1       0x        2017-08-17  0.211486
2       0x        2017-08-18  0.283789
3       0x        2017-08-19  0.511434
4       0x        2017-08-20  0.429522
...     ...       ...         ...
657311  zurcoin   2018-02-04  0.003254
657312  zurcoin   2018-02-05  0.002774
657313  zurcoin   2018-02-06  0.001986
657314  zurcoin   2018-02-09  0.002684
657315  zurcoin   2018-02-10  0.002325

我需要为每种货币的价格和日期设置一个列,作为索引,只有唯一的日期。会有很多空值,我打算用 0 替换。

date          0x_price  10mtoken_price  1337coin_price  ...
2017-08-16    1         4               (NaN)->0        ...
2017-08-17    2         5               (NaN)->0        ...
2017-08-18    3         6               7               ...
...           ...       ...             ...             ...

我尝试使用 groupby 遍历数据框,如下所示:

df2 = pd.DataFrame()
df2["date"] = df["Date"].unique()
df2.set_index("date", inplace=True)

for currency, group in df.groupby("Currency"):
df2.loc[df2.index.isin(group.Date), f"{currency}_price"] = group["Price"]

这返回了所需的列名和形状,但数据框填充了 NaN。

date          0x_price  10mtoken_price  1337coin_price  ...
2017-08-16    NaN       NaN             NaN             ...
2017-08-17    NaN       NaN             NaN             ...
2017-08-18    NaN       NaN             NaN             ...
...           ...       ...             ...             ...

我也尝试用 df.join() 实现同样的效果,如图所示:

df2 = pd.DataFrame()
df2["date"] = df["Date"].unique()
df2.set_index("date", inplace=True)

for currency, group in df.groupby("Currency"):
df2 = df2.join(group.set_index("Date")[["Price"]].rename(columns={"Price": f"{currency}_price"}))

在冻结我的计算机之前,这没有完成。也许它效率低下,我正在处理大约 650,000 个条目?

我无法在这里找到相同类型的问题,并且在查看文档后我无法找到解决方案。我可能错过了一些东西,但希望我已经充分描述了这个问题。提前致谢。

【问题讨论】:

    标签: python pandas


    【解决方案1】:

    Pandas pivot_table 可以在这里提供帮助。我会使用:

    resul = df.pivot_table(index=['Date'], columns=['Currency'], values=['Price']).fillna(0)
    

    使用您的示例数据,它给出:

                   Price          
    Currency          0x   zurcoin
    Date                          
    2017-08-16  0.111725  0.000000
    2017-08-17  0.211486  0.000000
    2017-08-18  0.283789  0.000000
    2017-08-19  0.511434  0.000000
    2017-08-20  0.429522  0.000000
    2018-02-04  0.000000  0.003254
    2018-02-05  0.000000  0.002774
    2018-02-06  0.000000  0.001986
    2018-02-09  0.000000  0.002684
    2018-02-10  0.000000  0.002325
    

    【讨论】:

    • 这很完美,我希望我可以选择多个答案!谢谢!
    【解决方案2】:

    如果您确定每种货币的每个日期只有 1 个价格,您可以这样做:

    df.groupby(['Date', 'Currency'])['Price'].mean().unstack().fillna(0)
    

    mean() 函数计算平均价格,如果在该日期该 ccy 的 df 中有多个价格。

    【讨论】:

    • 非常简单,完全按照要求工作。谢谢!
    【解决方案3】:

    我希望这适用于您的数据大小:

    for coin in set(df['Currency'].values):
        new_column_name = 'Price_'+coin
        df.assign(new_column_name = lambda x: x['Price']*(x['Currency']==coin))
    df.fillna(0).drop('Currency',axis=1).set_index('Date')
    

    【讨论】:

    • 感谢您的回答,我尝试了这个解决方案,也许我实施不正确,但是我在df.assin() 行收到了TypeError: 'Series' object is not callable。我能够使用上面的单线实现预期的结果,但再次感谢!
    • 对不起,我打错了:这个想法不是调用系列x['Price'],而是乘以下面的表达式(它被解释为True的1和False的0 )。
    • 除此之外,其他答案更清晰、更优化。永远不要在可以使用 pandas 内置函数的地方循环!
    猜你喜欢
    • 2019-09-26
    • 2013-02-18
    • 2016-12-17
    • 1970-01-01
    • 1970-01-01
    • 2019-05-01
    • 2021-01-04
    • 2021-08-28
    • 2018-02-04
    相关资源
    最近更新 更多