【问题标题】:Python long format: subtract selection of rowsPython长格式:减去行的选择
【发布时间】:2020-07-27 11:14:51
【问题描述】:

全部,

我有以下长格式数据框:

df = pd.DataFrame({'date': ["2020-01-01","2020-01-01","2020-01-02","2020-01-02","2020-01-01","2020-01-01","2020-01-02","2020-01-02"], 'asset': ["x", "x","x", "x","y","y","y","y"], 'type': ["price", "spread","price","spread","price", "spread","price","spread"], 'value': ["1.5", "0.01","1.6", "0.01","1","0.08","1.2","0.09"]})

看起来像这样:

         date asset    type value
0  2020-01-01     x   price   1.5
1  2020-01-01     x  spread  0.01
2  2020-01-02     x   price   1.6
3  2020-01-02     x  spread  0.01
4  2020-01-01     y   price     1
5  2020-01-01     y  spread  0.08
6  2020-01-02     y   price   1.2
7  2020-01-02     y  spread  0.09

我想从x 的价格中减去y 的价格并保持相同的数据结构,结果应该如下所示:

         date    asset       type value
0  2020-01-01        x      price   1.5
1  2020-01-01        x     spread  0.01
2  2020-01-02        x      price   1.6
3  2020-01-02        x     spread  0.01
4  2020-01-01        y      price     1
5  2020-01-01        y     spread  0.08
6  2020-01-02        y      price   1.2
7  2020-01-02        y     spread  0.09
8  2020-01-01  x_min_y  pricediff   0.5
9  2020-01-02  x_min_y  pricediff   0.4

我想使用 pandas 的 assign() 函数来创建它,但我不知道该怎么做。

提前致谢!

【问题讨论】:

  • pd.assign() 用于向数据框添加新列,它不能帮助您向数据框添加新行。您需要创建由这 2 行组成的数据框分隔,然后使用 pd.concat() 组装两者
  • @Deepak 您可以使用 assign 然后使用 melt() 来维护您的长数据帧结构。但是如何使用 assign() 并选择 x 和 y 的价格并减去呢?

标签: python pandas dataframe subtraction


【解决方案1】:

用途:

m = df['type'].eq('price') & df['asset'].isin(['x', 'y'])
d = df[m].pivot('date', 'asset', 'value').astype(float)

d = pd.concat(
    [df, d['x'].sub(d['y']).reset_index(name='value').assign(
        asset='x_min_y', type='pricediff')],
    ignore_index=True)

详情:

创建一个布尔掩码m 以过滤typepriceassetx, y 中的行,并使用DataFrame.pivot 重塑数据框:

print(d) # pivoted dataframe
asset         x    y
date                
2020-01-01  1.5  1.0
2020-01-02  1.6  1.2

使用Series.sub从透视数据帧中的y中减去列x并分配列assettype,然后使用pd.concat将这个透视数据帧与原始数据帧df连接起来.

print(d)
         date    asset       type value
0  2020-01-01        x      price   1.5
1  2020-01-01        x     spread  0.01
2  2020-01-02        x      price   1.6
3  2020-01-02        x     spread  0.01
4  2020-01-01        y      price     1
5  2020-01-01        y     spread  0.08
6  2020-01-02        y      price   1.2
7  2020-01-02        y     spread  0.09
8  2020-01-01  x_min_y  pricediff   0.5
9  2020-01-02  x_min_y  pricediff   0.4

【讨论】:

  • 看起来很有希望,我只是得到以下代码错误:df.query("type == 'price' & asset.isin(['x', 'y'])" ) TypeError: unhashable type: 'numpy.ndarray'
  • @JelleJansen 编码愉快! ;)
【解决方案2】:

假设不需要匹配日期并且数据集的定义如示例中那样,您可以执行以下操作:

df2 = pd.DataFrame(df1[df1["asset"] == "x" & df1["type"] == "price"]["value"].reset_index()["value"].astype(float)  - df1[df1["asset"] == "y" & df1["type"] == "price"]["value"].reset_index()["value"].astype(float))
df2["date"] = df1[df1["asset"] == "x"]["date"]
df2["type"] = df1[df1["asset"] == "x"]["type"]
df2["asset"] = "x_min_y"
pd.concat([df1,df2])

基本上,执行计算并在之后连接

【讨论】:

  • 感谢您的回答,但这似乎不是有效的编程。我正在寻找有效的语法,我不需要像你那样对每列进行操作,而是在一行代码中设置它(我习惯于使用 R 和 R dplyr)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-11-11
  • 2022-01-21
  • 1970-01-01
  • 2021-08-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多