Pandas Dataframe:将对角线子帧减少为单行或如何逐个填充数据帧

Posted

技术标签:

【中文标题】Pandas Dataframe:将对角线子帧减少为单行或如何逐个填充数据帧【英文标题】:Pandas Dataframe: Reduce Diagonal Sub-Frame to Single Row or How to Fill a Dataframe Piece by Piece 【发布时间】:2014-07-06 20:02:53 【问题描述】:

在客户端/服务器应用程序中,从服务器请求数据,并使用请求 id 映射传入的回复:

--> Request data for item i using request_id 1
--> Request data for item j using request_id 2
:
<-- Data element i.p for request_id1
<-- Data element j.p for request_id2
<-- Data element i.q for request_id1
<-- Data element j.q for request_id2
<-- Data element i.r for request_id1
<-- Data element j.r for request_id2

传入的块被添加到字典列表中,由以下代码模拟:

import pandas
import random

md = list()
md.append('request_id': 1, 'p': random.random())
md.append('request_id': 2, 'p': random.random())
md.append('request_id': 1, 'q': random.random())
md.append('request_id': 2, 'q': random.random())
md.append('request_id': 1, 'r': random.random())
md.append('request_id': 2, 'r': random.random())

df = pandas.DataFrame(md).set_index('request_id')

print df

从列表 md 创建数据框时,每行只有一列有值,其他所有列都是 NaN。上面的代码产生以下结果:

                   p         q         r
request_id                              
1           0.955755       NaN       NaN
2           0.920858       NaN       NaN
1                NaN  0.583634       NaN
2                NaN  0.456644       NaN
1                NaN       NaN  0.198991
2                NaN       NaN  0.774762

[6 rows x 3 columns]

如何将 df 减少到每个 request_id 仅一行?我真正需要的是以下内容:

                   p         q         r
request_id                              
1           0.955755  0.583634  0.198991
2           0.920858  0.456644  0.774762

[2 rows x 3 columns]

块没有特定的顺序进入,并且对于每个请求,都会收到请求结束消息。保证每个块只发送一次(如果有的话),因此每行只有一个(或零)数据元素不是 NaN。

一个典型的应用是期权链的异步数据检索,其中包含每个单一期权的各种数据元素,例如价格、IV、Delta、Gamma、Theta、Vega。

【问题讨论】:

【参考方案1】:

也许不是使用字典列表,而是将md 设为字典的字典:

import pandas
import random
import collections

md = collections.defaultdict(dict)
md['p'][1] = random.random()
md['p'][2] = random.random()
md['q'][2] = random.random()
md['q'][1] = random.random()
md['r'][1] = random.random()
md['r'][2] = random.random()

df = pandas.DataFrame(md)
df.index.name = 'request_id'

print df

产生类似的东西

                   p         q         r
request_id                              
1           0.127898  0.565351  0.966917
2           0.983144  0.593652  0.617639

[2 rows x 3 columns]

虽然创建一个大的DataFrame效率低下,只是为了以后缩小它,如果你必须使用一个dicts列表,你可以像这样组合行:

import pandas as pd
import random

md = list()
md.append('request_id': 1, 'p': random.random())
md.append('request_id': 2, 'p': random.random())
md.append('request_id': 1, 'q': random.random())
md.append('request_id': 2, 'q': random.random())
md.append('request_id': 1, 'r': random.random())
md.append('request_id': 2, 'r': random.random())
df = pd.DataFrame(md).set_index('request_id')
df = pd.concat([df[col].dropna() for col in df.columns], axis=1)
print(df)

这会从每一列中删除 NaN,然后​​使用 pd.concat 将 Series 列表合并到一个 DataFrame 中。

【讨论】:

您使用defaultdict(dict) 的提示非常棒,而且效果很好。我没有考虑过这一点,也从未使用过defaultdict 子类。感谢您花时间查看我的代码 sn-p 并为我指明正确的方向!

以上是关于Pandas Dataframe:将对角线子帧减少为单行或如何逐个填充数据帧的主要内容,如果未能解决你的问题,请参考以下文章

pandas对角线值修改

将修改后的子帧嵌入到原始子帧中

按行切片 Pandas DataFrame

将 Pandas Multiindexed DataFrame 与 Singleindexed Pandas DataFrame 合并

pandas-18 reindex用法

Pandas - 将 DataFrame 值除以 MultiIndex DataFrame 中的系列