Python 熊猫和缺失值中特定组之间的多索引和操作
考虑以下按对(A,B)索引的单列表: 对于B的一个特定值,比如b2,我想得到一个表,列出它的所有值,以及一个额外的列,如果存在b1或b2的对应值,则给出b2和b1之间的差异。因此,结果应该是:Python 熊猫和缺失值中特定组之间的多索引和操作,python,pandas,Python,Pandas,考虑以下按对(A,B)索引的单列表: 对于B的一个特定值,比如b2,我想得到一个表,列出它的所有值,以及一个额外的列,如果存在b1或b2的对应值,则给出b2和b1之间的差异。因此,结果应该是: b2 b2-b1 a1 3.0 2.0 a2 30.0 20.0 a3 NaN NaN a4 40.0 NaN 其中a3的两列中的NaN表示b1和b2的值都缺失,而a4的NaN表示只有b1缺失 最初,我尝试的解决方案基于: 但这样就得到了一个没有a3行的表
b2 b2-b1
a1 3.0 2.0
a2 30.0 20.0
a3 NaN NaN
a4 40.0 NaN
其中a3的两列中的NaN表示b1和b2的值都缺失,而a4的NaN表示只有b1缺失
最初,我尝试的解决方案基于:
但这样就得到了一个没有a3行的表(列名可以通过重命名来固定):
这样做的原因是转换似乎保留了原始索引,并且额外的NaN没有插入到表中,对吗?有可能解决这个问题吗
因此,我尝试了一种组中列之间显式差异的替代方法:
import numpy as np
import pandas as pd
import itertools
index = pd.MultiIndex.from_tuples([
('a1', 'b1'),
('a1', 'b2'),
('a2', 'b1'),
('a2', 'b2'),
('a3', 'b1'),
('a4', 'b2'),
], names=['A', 'B'])
input_table = pd.DataFrame({'Value': [1,3, 10, 30, 100, 40]}, index=index)
grouped = input_table.groupby(level='B')
b1 = grouped.get_group('b1')
b1.index = b1.index.droplevel(level='B')
b2 = grouped.get_group('b2')
b2.index = b2.index.droplevel(level='B')
b2 = b2.rename(columns={'Value': 'b2'})
b2 = pd.concat([b2, b2['b2'] - b1['Value']], axis=1)
b2.rename(columns={0: 'b2-b1'}, inplace=True)
print(b2)
这是可行的,但由于所有代码都要降低级别,所以列之间的差异可以工作,而分隔的列可以重命名,这似乎相当复杂。
有没有可能使它更简单?使用
unstack
将B
放到列上,使用assign
创建b2-b1
和drop
删除不需要的列
In [1120]: table.unstack()['Value'].assign(b2b1=lambda x: x.b2-x.b1).drop(['b1', 'b3'], 1)
Out[1120]:
B b2 b2b1
A
a1 3.0 2.0
a2 30.0 20.0
a3 NaN NaN
a4 40.0 NaN
要删除索引名,请使用重命名\u轴
In [1123]: (table.unstack()['Value'].assign(b2b1=lambda x: x.b2-x.b1).drop(['b1', 'b3'], 1)
.rename_axis(None).rename_axis(None, 1))
Out[1123]:
b2 b2b1
a1 3.0 2.0
a2 30.0 20.0
a3 NaN NaN
a4 40.0 NaN
或者,您可以存储
取消堆栈
结果
In [1127]: dff = table.unstack()['Value'].rename_axis(None).rename_axis(None, 1)
In [1128]: dff['b2-b1'] = dff['b2'] - dff['b1']
In [1129]: dff
Out[1129]:
b1 b2 b3 b2-b1
a1 1.0 3.0 NaN 2.0
a2 10.0 30.0 31.0 20.0
a3 100.0 NaN NaN NaN
a4 NaN 40.0 NaN NaN
In [1189]: dff[['b1', 'b2-b1']] # get specific columns
Out[1189]:
b1 b2-b1
a1 1.0 2.0
a2 10.0 20.0
a3 100.0 NaN
a4 NaN NaN
细节
In [1124]: table.unstack()
Out[1124]:
Value
B b1 b2 b3
A
a1 1.0 3.0 NaN
a2 10.0 30.0 31.0
a3 100.0 NaN NaN
a4 NaN 40.0 NaN
是否可以避免硬编码要删除的列的名称?即除去“b1”列以外的所有列?在我的例子中,表可能有相当多的B值。谢谢!现在我得到了unstack的可用性:)
In [1123]: (table.unstack()['Value'].assign(b2b1=lambda x: x.b2-x.b1).drop(['b1', 'b3'], 1)
.rename_axis(None).rename_axis(None, 1))
Out[1123]:
b2 b2b1
a1 3.0 2.0
a2 30.0 20.0
a3 NaN NaN
a4 40.0 NaN
In [1127]: dff = table.unstack()['Value'].rename_axis(None).rename_axis(None, 1)
In [1128]: dff['b2-b1'] = dff['b2'] - dff['b1']
In [1129]: dff
Out[1129]:
b1 b2 b3 b2-b1
a1 1.0 3.0 NaN 2.0
a2 10.0 30.0 31.0 20.0
a3 100.0 NaN NaN NaN
a4 NaN 40.0 NaN NaN
In [1189]: dff[['b1', 'b2-b1']] # get specific columns
Out[1189]:
b1 b2-b1
a1 1.0 2.0
a2 10.0 20.0
a3 100.0 NaN
a4 NaN NaN
In [1124]: table.unstack()
Out[1124]:
Value
B b1 b2 b3
A
a1 1.0 3.0 NaN
a2 10.0 30.0 31.0
a3 100.0 NaN NaN
a4 NaN 40.0 NaN