如何创建一个数据透视表 table 索引在一个包含重复条目的列上,这些条目应该按另一列的值进行分组?
How can I create a pivot table indexed on a column with duplicate entries that should be grouped by values of another column?
假设我有一个这样的数据框
import pandas as pd
df = pd.DataFrame({'key1': ['id1','id1','id1','id1','id2','id2','id2','id3'],
'key2': ['MIN','MIN','MAX','MAX','MIN','MIN','MAX','MIN'],
'key3': [0,1,0,1,0,2,1,0],
'value': [-1,-2,11,12,-4,0,9,-2]})
print(df)
key1 key2 key3 value
0 id1 MIN 0 -1
1 id1 MIN 1 -2
2 id1 MAX 0 11
3 id1 MAX 1 12
4 id2 MIN 0 -4
5 id2 MIN 2 0
6 id2 MAX 1 9
7 id3 MIN 0 -2
考虑到:
key1
和 key2
列中的值不唯一
key3
的值与我们的任务无关(因此我们可以根据需要对它们进行分组、聚合或过滤)
我想创建一个枢轴 table 其中:
- 该索引具有
key1
的唯一值
- 这些列是
key2
的唯一值(我们可以假设它们只是 MAX 和 MIN)
- MAX 列中的值是给定值
key1
的原始数据帧中值的最大值,其中 key2
=MAX
- 对于
key1
的给定值,MIN 列中的值是原始数据框中值的最小值,其中 key2
=MIN
所以,对于给定的输入,输出应该是
MIN MAX
id1 -2 12
id2 -4 9
id3 -2 NaN
如果我尝试在数据帧上使用 pivot
函数,我会得到一个 ValueError
因为 key1
有重复值
df.pivot(index='key1', columns='key2', values='value')
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-19-eee9e613bc28> in <module>
----> 1 df.pivot(index='key1', columns='key2', values='value')
2 # ValueError: Index contains duplicate entries, cannot reshape
而且我不能使用 groupby
函数,因为它会将 MIN 和 MAX 值聚合在一起
print(df.groupby('key1').agg(MIN=('value', 'min'), MAX=('value', 'max')))
MIN MAX
key1
id1 -2 12
id2 -4 9
id3 -2 -2
有没有比创建两个单独的系列(一个用于 MIN 值,一个用于 MAX 值;通常,key2
中的每个不同值都是一个系列)更优雅的解决方案?
min_series=df[df['key2'].eq('MIN')].groupby('key1').min()['value']
max_series=df[df['key2'].eq('MAX')].groupby('key1').max()['value']
print(pd.DataFrame({'MIN':min_series, 'MAX':max_series}))
MIN MAX
id1 -2 12.0
id2 -4 9.0
id3 -2 NaN
这是解决问题的一种方法,方法是在 key1
和 key2
上对数据帧进行分组,然后根据 [=] 指定的聚合函数对每个子组聚合列 value
13=]:
d = {k: v.agg(k[1].lower()) for k, v in df.groupby(['key1', 'key2'])['value']}
frame = pd.Series(d).unstack()
>>> frame
MAX MIN
id1 12.0 -2.0
id2 9.0 -4.0
id3 NaN -2.0
这是一种方法,使用 set_index
和 unstack
为 key2 的每个值创建一个列。然后你可以使用 groupby
并在 agg
中为 key2
的每个值定义你想要的
res = (df.set_index('key2', append=True)
['value'].unstack()
.groupby(df['key1'])
.agg({'MAX':'max', 'MIN':'min'})
)
print(res)
MAX MIN
key1
id1 12.0 -2.0
id2 9.0 -4.0
id3 NaN -2.0
假设我有一个这样的数据框
import pandas as pd
df = pd.DataFrame({'key1': ['id1','id1','id1','id1','id2','id2','id2','id3'],
'key2': ['MIN','MIN','MAX','MAX','MIN','MIN','MAX','MIN'],
'key3': [0,1,0,1,0,2,1,0],
'value': [-1,-2,11,12,-4,0,9,-2]})
print(df)
key1 key2 key3 value
0 id1 MIN 0 -1
1 id1 MIN 1 -2
2 id1 MAX 0 11
3 id1 MAX 1 12
4 id2 MIN 0 -4
5 id2 MIN 2 0
6 id2 MAX 1 9
7 id3 MIN 0 -2
考虑到:
key1
和key2
列中的值不唯一key3
的值与我们的任务无关(因此我们可以根据需要对它们进行分组、聚合或过滤)
我想创建一个枢轴 table 其中:
- 该索引具有
key1
的唯一值
- 这些列是
key2
的唯一值(我们可以假设它们只是 MAX 和 MIN) - MAX 列中的值是给定值
key1
的原始数据帧中值的最大值,其中key2
=MAX - 对于
key1
的给定值,MIN 列中的值是原始数据框中值的最小值,其中key2
=MIN
所以,对于给定的输入,输出应该是
MIN MAX
id1 -2 12
id2 -4 9
id3 -2 NaN
如果我尝试在数据帧上使用 pivot
函数,我会得到一个 ValueError
因为 key1
有重复值
df.pivot(index='key1', columns='key2', values='value')
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-19-eee9e613bc28> in <module>
----> 1 df.pivot(index='key1', columns='key2', values='value')
2 # ValueError: Index contains duplicate entries, cannot reshape
而且我不能使用 groupby
函数,因为它会将 MIN 和 MAX 值聚合在一起
print(df.groupby('key1').agg(MIN=('value', 'min'), MAX=('value', 'max')))
MIN MAX
key1
id1 -2 12
id2 -4 9
id3 -2 -2
有没有比创建两个单独的系列(一个用于 MIN 值,一个用于 MAX 值;通常,key2
中的每个不同值都是一个系列)更优雅的解决方案?
min_series=df[df['key2'].eq('MIN')].groupby('key1').min()['value']
max_series=df[df['key2'].eq('MAX')].groupby('key1').max()['value']
print(pd.DataFrame({'MIN':min_series, 'MAX':max_series}))
MIN MAX
id1 -2 12.0
id2 -4 9.0
id3 -2 NaN
这是解决问题的一种方法,方法是在 key1
和 key2
上对数据帧进行分组,然后根据 [=] 指定的聚合函数对每个子组聚合列 value
13=]:
d = {k: v.agg(k[1].lower()) for k, v in df.groupby(['key1', 'key2'])['value']}
frame = pd.Series(d).unstack()
>>> frame
MAX MIN
id1 12.0 -2.0
id2 9.0 -4.0
id3 NaN -2.0
这是一种方法,使用 set_index
和 unstack
为 key2 的每个值创建一个列。然后你可以使用 groupby
并在 agg
中为 key2
res = (df.set_index('key2', append=True)
['value'].unstack()
.groupby(df['key1'])
.agg({'MAX':'max', 'MIN':'min'})
)
print(res)
MAX MIN
key1
id1 12.0 -2.0
id2 9.0 -4.0
id3 NaN -2.0