我有一个Pandas数据框,它有两个关键列,我想确保表中存在这些键的笛卡尔积(因为我必须制作一个包含所有组合的2D图).我无法想出一个相当简短和惯用的方法来做到这一点.
例如,我从这张表开始,给出水果和蔬菜的组合,以及它们如何一起品尝:
combo fruit veg
0 tasty apple carrot
1 yucky banana carrot
2 tasty banana lettuce
3 yucky lemon lettuce
Run Code Online (Sandbox Code Playgroud)
我想最终得到所有可能组合的表:
fruit veg combo
0 apple carrot tasty
1 apple lettuce UNKNOWN
2 banana carrot yucky
3 banana lettuce tasty
4 lemon carrot UNKNOWN
5 lemon lettuce yucky
Run Code Online (Sandbox Code Playgroud)
这是我发现的最佳方式:
import pandas as pd
# Initial data
df=pd.DataFrame(dict(fruit=['apple','banana','banana','lemon'],
veg=['carrot','carrot','lettuce','lettuce'],
combo=['tasty','yucky','tasty','yucky']))
# Solution starts here
veg=df.groupby('veg').size().reset_index()
fruit=df.groupby('fruit').size().reset_index()
fruit[0] = veg[0] = 0 #use this dummy column for the join to work!
cartesian = pd.merge(fruit, veg, how='outer', on=0)
del cartesian[0]
all_combos = pd.merge(cartesian, df, how='left')
all_combos[ pd.isnull(all_combos.combo) ] = 'UNKNOWN'
Run Code Online (Sandbox Code Playgroud)
我想有一个更简单,更不易出错的方法来做这个...任何建议?
我特别感激,如果有人可以告诉我如何在有和没有包含fruit
和veg
列的多索引的情况下这样做,因为我真的很难过如何使用索引来做这件事.根据我的SQL经验,我认为这些正是索引所针对的情况.
And*_*den 11
在这个回答后的某个时候,我加入cartesian_product
了熊猫,不久之后MultiIndex.from_product
又添加了(在另一个问题中提出建议).这使得以下简化更有效:
In [21]: p = pd.MultiIndex.from_product(df1.index.levels, names=df1.index.names)
In [22]: df1.reindex(p, fill_value='UNKNOWN')
Out[22]:
combo
fruit veg
apple carrot tasty
lettuce UNKNOWN
banana carrot yucky
lettuce tasty
lemon carrot UNKNOWN
lettuce yucky
Run Code Online (Sandbox Code Playgroud)
较老的答案如下:
如果您使用水果和蔬菜作为索引,那么您可以使用itertools.product
*来创建MultiIndex
to reindex
:
In [10]: from itertools import product
In [11]: df
Out[11]:
combo fruit veg
0 tasty apple carrot
1 yucky banana carrot
2 tasty banana lettuce
3 yucky lemon lettuce
Run Code Online (Sandbox Code Playgroud)
棘手的部分是获取所有可能的水果/蔬菜的正确MultiIndex:
In [12]: fruit_x_veg = list(product(np.unique(df['fruit']), np.unique(df['veg'])))
In [13]: fruit_x_veg = pd.MultiIndex.from_tuples(fruit_x_veg,
names=['fruit', 'veg'])
Run Code Online (Sandbox Code Playgroud)
然后你可以通过这些重新索引:
In [14]: df1 = df.set_index(['fruit', 'veg'])
In [15]: df1
Out[15]:
combo
fruit veg
apple carrot tasty
banana carrot yucky
lettuce tasty
lemon lettuce yucky
In [16]: df1.reindex(fruit_x_veg, fill_value='UNKNOWN')
Out[16]:
combo
fruit veg
apple carrot tasty
lettuce UNKNOWN
banana carrot yucky
lettuce tasty
lemon carrot UNKNOWN
lettuce yucky
Run Code Online (Sandbox Code Playgroud)
*如果itertools.product
速度不够快,请考虑使用这个numpy实现
注意:此实现扩展了pandas.tools.util.cartesian_product
,现在支持更多dtypes(并在引擎盖下使用MultiIndex.from_product
).
归档时间: |
|
查看次数: |
2503 次 |
最近记录: |