Join 在部分匹配索引上联接数据帧
我试图找到一种更优雅的方式来连接两个Join 在部分匹配索引上联接数据帧,join,pandas,Join,Pandas,我试图找到一种更优雅的方式来连接两个数据帧s,其中一个DF的索引级别是另一个DF的索引级别的部分子集。这是SQL中非常常见的操作,我惊讶地发现使用pandas很难做到: 下面是一个例子: import pandas as pd df = pd.DataFrame( { 2012:[4,5,8,9], 2013:[1,2,4,7], 2014:[6,5,4,3], }, index= pd.MultiIndex.from_t
数据帧
s,其中一个DF的索引级别是另一个DF的索引级别的部分子集。这是SQL中非常常见的操作,我惊讶地发现使用pandas
很难做到:
下面是一个例子:
import pandas as pd
df = pd.DataFrame(
{
2012:[4,5,8,9],
2013:[1,2,4,7],
2014:[6,5,4,3],
},
index= pd.MultiIndex.from_tuples([('apples',False),('bananas',False),('oranges',True),('lemons',True)], names=('fruit','citrus'))
)
=>
现在我想知道一年中每种水果的最高销售量:
fruit_max_by_date = df.max(axis=1).to_frame()
citrus_max_by_date = fruit_max_by_date.max(level='citrus')
citrus_max_by_date.columns = [1]
=>
到目前为止还不错。但现在我尝试将后两者结合起来:
fruit_max_by_date.join(citrus_max_by_date) =>
0 1
fruit citrus
apples False 6 NaN
bananas False 5 NaN
oranges True 8 NaN
lemons True 9 NaN
[4 rows x 2 columns]
啊因为第二个表的索引与第一个表的索引不完全匹配,所以连接失败。这似乎与类似SQL的内部联接的直观行为完全相反
下面的所有解决方法(尤其是第二种)都很糟糕,基本上要么将索引抛出窗口,要么手动广播一个表的索引有更简单的方法吗?
解决方法:通过广播扩展较小表的索引
这是我能想到的最不难看的解决方法,但它仍然非常糟糕,因为它需要毫无理由地扩展第二个数组的大小
fruit_max_by_date.join(
citrus_max_by_date.reindex(fruit_max_by_date.index, level='citrus') ) =>
0 1
fruit citrus
apples False 6 6
bananas False 5 6
oranges True 8 9
lemons True 9 9
[4 rows x 2 columns]
解决方法:截断第一个表的索引
这是非常丑陋的,尤其是必须在事后重新组装索引,但它是有效的
fruit_max_by_date \
.reset_index(level='fruit') \
.join(citrus_max_by_date) \
.set_index('fruit',append=True \
.reorder_levels((1,0)) =>
0 1
citrus fruit
False apples 6 6
bananas 5 6
True oranges 8 9
lemons 9 9
[4 rows x 2 columns]
放弃所有使用索引的伪装,加入而不使用索引
好的,这是相对简单的,但是如果你不能使用索引,那么拥有索引到底有什么意义呢
如果使用join
-而不是merge
(FML!!)-还有另一个奇怪的副作用:在输出中,join-列被重复:
fruit_max_by_date.reset_index().join(
citrus_max_by_date.reset_index(),
on='citrus', rsuffix='_' ) =>
fruit citrus 0 citrus_ 1
0 apples False 6 False 6
1 bananas False 5 False 6
2 oranges True 8 True 9
3 lemons True 9 True 9
[4 rows x 5 columns]
fruit_max_by_date.reset_index().merge(
citrus_max_by_date.reset_index(),
on='citrus' ) =>
fruit citrus 0 1
0 apples False 6 6
1 bananas False 5 6
2 oranges True 8 9
3 lemons True 9 9
[4 rows x 4 columns]
你用的是什么版本?我使用最新版本(0.16.2)没有任何问题。这可能是在版本0.14.0中添加的?啊。。。谢谢我在0.13。。。应该已经升级了吗-(
fruit_max_by_date \
.reset_index(level='fruit') \
.join(citrus_max_by_date) \
.set_index('fruit',append=True \
.reorder_levels((1,0)) =>
0 1
citrus fruit
False apples 6 6
bananas 5 6
True oranges 8 9
lemons 9 9
[4 rows x 2 columns]
fruit_max_by_date.reset_index().join(
citrus_max_by_date.reset_index(),
on='citrus', rsuffix='_' ) =>
fruit citrus 0 citrus_ 1
0 apples False 6 False 6
1 bananas False 5 False 6
2 oranges True 8 True 9
3 lemons True 9 True 9
[4 rows x 5 columns]
fruit_max_by_date.reset_index().merge(
citrus_max_by_date.reset_index(),
on='citrus' ) =>
fruit citrus 0 1
0 apples False 6 6
1 bananas False 5 6
2 oranges True 8 9
3 lemons True 9 9
[4 rows x 4 columns]