这是我们可以用来进行透视的习语列表
-
pd.DataFrame.pivot_table
- 一个美化版本
groupby
具有更直观的 API。对于许多人来说,这是首选方法。这是开发人员的预期方法。
- 指定行级别、列级别、要聚合的值以及执行聚合的函数。
-
pd.DataFrame.groupby + pd.DataFrame.unstack
- 适用于任何类型的枢轴的良好通用方法
- 您指定将构成一组依据中的透视行级别和列级别的所有列。接下来,您可以选择要聚合的其余列以及要执行聚合的函数。最后,你
unstack
您希望在列索引中的级别。
-
pd.DataFrame.set_index + pd.DataFrame.unstack
- 对于某些人(包括我自己)来说方便且直观。无法处理重复的分组键。
- 类似于
groupby
范例中,我们指定最终将成为行或列级别的所有列,并将它们设置为索引。然后我们unstack
我们想要在列中显示的级别。如果剩余的索引级别或列级别不唯一,则此方法将失败。
-
pd.DataFrame.pivot
- 非常类似于
set_index
因为它有重复键的限制。 API 也非常有限。它只需要标量值index
, columns
, values
.
- 类似于
pivot_table
方法,我们选择要旋转的行、列和值。但是,我们无法聚合,如果行或列不唯一,则此方法将失败。
-
pd.crosstab
- 这是一个专门版本
pivot_table
最纯粹的形式是执行多项任务的最直观的方式。
-
pd.factorize + np.bincount
- 这是一项非常先进的技术,虽然非常晦涩,但速度非常快。它不可能在所有情况下都使用,但是当它可以使用并且您可以轻松使用它时,您将获得性能奖励。
-
pd.get_dummies + pd.DataFrame.dot
也可以看看:
问题1
为什么我得到ValueError: Index contains duplicate entries, cannot reshape
发生这种情况是因为 pandas 试图重新索引columns
or index
具有重复条目的对象。有多种方法可以用来执行枢转。其中一些不太适合当要求旋转的键重复时。例如:考虑pd.DataFrame.pivot
。我知道有重复的条目共享row
and col
values:
df.duplicated(['row', 'col']).any()
True
所以当我pivot
using
df.pivot(index='row', columns='col', values='val0')
我收到上面提到的错误。事实上,当我尝试使用以下命令执行相同的任务时,我遇到了相同的错误:
df.set_index(['row', 'col'])['val0'].unstack()
Examples
对于后续的每个问题,我要做的就是使用pd.DataFrame.pivot_table。然后我将提供执行相同任务的替代方案。
问题2和3
我如何旋转df
使得col
值是列,row
值是索引和平均值val0
价值观是什么?
-
pd.DataFrame.pivot_table
df.pivot_table(
values='val0', index='row', columns='col',
aggfunc='mean')
col col0 col1 col2 col3 col4
row
row0 0.77 0.605 NaN 0.860 0.65
row2 0.13 NaN 0.395 0.500 0.25
row3 NaN 0.310 NaN 0.545 NaN
row4 NaN 0.100 0.395 0.760 0.24
-
aggfunc='mean'
是默认值,我不需要设置它。我把它包括在内是为了明确。
怎样才能让缺失值变成0呢?
-
pd.DataFrame.pivot_table
-
fill_value
默认情况下未设置。我倾向于适当地设置它。在本例中我将其设置为0
.
df.pivot_table(
values='val0', index='row', columns='col',
fill_value=0, aggfunc='mean')
col col0 col1 col2 col3 col4
row
row0 0.77 0.605 0.000 0.860 0.65
row2 0.13 0.000 0.395 0.500 0.25
row3 0.00 0.310 0.000 0.545 0.00
row4 0.00 0.100 0.395 0.760 0.24
-
pd.DataFrame.groupby
df.groupby(['row', 'col'])['val0'].mean().unstack(fill_value=0)
-
pd.crosstab
pd.crosstab(
index=df['row'], columns=df['col'],
values=df['val0'], aggfunc='mean').fillna(0)
问题4
除了mean
,就像也许sum
?
-
pd.DataFrame.pivot_table
df.pivot_table(
values='val0', index='row', columns='col',
fill_value=0, aggfunc='sum')
col col0 col1 col2 col3 col4
row
row0 0.77 1.21 0.00 0.86 0.65
row2 0.13 0.00 0.79 0.50 0.50
row3 0.00 0.31 0.00 1.09 0.00
row4 0.00 0.10 0.79 1.52 0.24
-
pd.DataFrame.groupby
df.groupby(['row', 'col'])['val0'].sum().unstack(fill_value=0)
-
pd.crosstab
pd.crosstab(
index=df['row'], columns=df['col'],
values=df['val0'], aggfunc='sum').fillna(0)
问题5
我可以一次进行多个聚合吗?
请注意,对于pivot_table
and crosstab
我需要传递可调用列表。另一方面,groupby.agg
能够将字符串用于有限数量的特殊函数。groupby.agg
也会采用我们传递给其他人的相同可调用函数,但利用字符串函数名称通常更有效,因为可以提高效率。
-
pd.DataFrame.pivot_table
df.pivot_table(
values='val0', index='row', columns='col',
fill_value=0, aggfunc=[np.size, np.mean])
size mean
col col0 col1 col2 col3 col4 col0 col1 col2 col3 col4
row
row0 1 2 0 1 1 0.77 0.605 0.000 0.860 0.65
row2 1 0 2 1 2 0.13 0.000 0.395 0.500 0.25
row3 0 1 0 2 0 0.00 0.310 0.000 0.545 0.00
row4 0 1 2 2 1 0.00 0.100 0.395 0.760 0.24
-
pd.DataFrame.groupby
df.groupby(['row', 'col'])['val0'].agg(['size', 'mean']).unstack(fill_value=0)
-
pd.crosstab
pd.crosstab(
index=df['row'], columns=df['col'],
values=df['val0'], aggfunc=[np.size, np.mean]).fillna(0, downcast='infer')
问题6
我可以聚合多个值列吗?
-
pd.DataFrame.pivot_table我们通过values=['val0', 'val1']
但我们可以完全放弃它
df.pivot_table(
values=['val0', 'val1'], index='row', columns='col',
fill_value=0, aggfunc='mean')
val0 val1
col col0 col1 col2 col3 col4 col0 col1 col2 col3 col4
row
row0 0.77 0.605 0.000 0.860 0.65 0.01 0.745 0.00 0.010 0.02
row2 0.13 0.000 0.395 0.500 0.25 0.45 0.000 0.34 0.440 0.79
row3 0.00 0.310 0.000 0.545 0.00 0.00 0.230 0.00 0.075 0.00
row4 0.00 0.100 0.395 0.760 0.24 0.00 0.070 0.42 0.300 0.46
-
pd.DataFrame.groupby
df.groupby(['row', 'col'])['val0', 'val1'].mean().unstack(fill_value=0)
问题7
我可以细分多列吗?
-
pd.DataFrame.pivot_table
df.pivot_table(
values='val0', index='row', columns=['item', 'col'],
fill_value=0, aggfunc='mean')
item item0 item1 item2
col col2 col3 col4 col0 col1 col2 col3 col4 col0 col1 col3 col4
row
row0 0.00 0.00 0.00 0.77 0.00 0.00 0.00 0.00 0.00 0.605 0.86 0.65
row2 0.35 0.00 0.37 0.00 0.00 0.44 0.00 0.00 0.13 0.000 0.50 0.13
row3 0.00 0.00 0.00 0.00 0.31 0.00 0.81 0.00 0.00 0.000 0.28 0.00
row4 0.15 0.64 0.00 0.00 0.10 0.64 0.88 0.24 0.00 0.000 0.00 0.00
-
pd.DataFrame.groupby
df.groupby(
['row', 'item', 'col']
)['val0'].mean().unstack(['item', 'col']).fillna(0).sort_index(1)
问题8
我可以细分多列吗?
-
pd.DataFrame.pivot_table
df.pivot_table(
values='val0', index=['key', 'row'], columns=['item', 'col'],
fill_value=0, aggfunc='mean')
item item0 item1 item2
col col2 col3 col4 col0 col1 col2 col3 col4 col0 col1 col3 col4
key row
key0 row0 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.86 0.00
row2 0.00 0.00 0.37 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.50 0.00
row3 0.00 0.00 0.00 0.00 0.31 0.00 0.81 0.00 0.00 0.00 0.00 0.00
row4 0.15 0.64 0.00 0.00 0.00 0.00 0.00 0.24 0.00 0.00 0.00 0.00
key1 row0 0.00 0.00 0.00 0.77 0.00 0.00 0.00 0.00 0.00 0.81 0.00 0.65
row2 0.35 0.00 0.00 0.00 0.00 0.44 0.00 0.00 0.00 0.00 0.00 0.13
row3 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.28 0.00
row4 0.00 0.00 0.00 0.00 0.10 0.00 0.00 0.00 0.00 0.00 0.00 0.00
key2 row0 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.40 0.00 0.00
row2 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.13 0.00 0.00 0.00
row4 0.00 0.00 0.00 0.00 0.00 0.64 0.88 0.00 0.00 0.00 0.00 0.00
-
pd.DataFrame.groupby
df.groupby(
['key', 'row', 'item', 'col']
)['val0'].mean().unstack(['item', 'col']).fillna(0).sort_index(1)
-
pd.DataFrame.set_index因为该组键对于行和列都是唯一的
df.set_index(
['key', 'row', 'item', 'col']
)['val0'].unstack(['item', 'col']).fillna(0).sort_index(1)
问题9
我可以聚合列和行一起出现的频率,也称为“交叉制表”吗?
-
pd.DataFrame.pivot_table
df.pivot_table(index='row', columns='col', fill_value=0, aggfunc='size')
col col0 col1 col2 col3 col4
row
row0 1 2 0 1 1
row2 1 0 2 1 2
row3 0 1 0 2 0
row4 0 1 2 2 1
-
pd.DataFrame.groupby
df.groupby(['row', 'col'])['val0'].size().unstack(fill_value=0)
-
pd.crosstab
pd.crosstab(df['row'], df['col'])
-
pd.factorize + np.bincount
# get integer factorization `i` and unique values `r`
# for column `'row'`
i, r = pd.factorize(df['row'].values)
# get integer factorization `j` and unique values `c`
# for column `'col'`
j, c = pd.factorize(df['col'].values)
# `n` will be the number of rows
# `m` will be the number of columns
n, m = r.size, c.size
# `i * m + j` is a clever way of counting the
# factorization bins assuming a flat array of length
# `n * m`. Which is why we subsequently reshape as `(n, m)`
b = np.bincount(i * m + j, minlength=n * m).reshape(n, m)
# BTW, whenever I read this, I think 'Bean, Rice, and Cheese'
pd.DataFrame(b, r, c)
col3 col2 col0 col1 col4
row3 2 0 0 1 0
row2 1 2 1 0 2
row0 1 0 1 2 1
row4 2 2 0 1 1
-
pd.get_dummies
pd.get_dummies(df['row']).T.dot(pd.get_dummies(df['col']))
col0 col1 col2 col3 col4
row0 1 2 0 1 1
row2 1 0 2 1 2
row3 0 1 0 2 0
row4 0 1 2 2 1
问题10
如何通过仅旋转两个数据帧将数据帧从长转换为宽
列?
-
DataFrame.pivot
第一步是为每一行分配一个数字 - 该数字将是透视结果中该值的行索引。这是使用完成的GroupBy.cumcount:
df2.insert(0, 'count', df2.groupby('A').cumcount())
df2
count A B
0 0 a 0
1 1 a 11
2 2 a 2
3 3 a 11
4 0 b 10
5 1 b 10
6 2 b 14
7 0 c 7
第二步,使用新创建的列作为索引来调用DataFrame.pivot.
df2.pivot(*df2)
# df2.pivot(index='count', columns='A', values='B')
A a b c
count
0 0.0 10.0 7.0
1 11.0 10.0 NaN
2 2.0 14.0 NaN
3 11.0 NaN NaN
-
DataFrame.pivot_table
Whereas DataFrame.pivot只接受列,DataFrame.pivot_table也接受数组,所以GroupBy.cumcount
可以直接传递为index
无需创建显式列。
df2.pivot_table(index=df2.groupby('A').cumcount(), columns='A', values='B')
A a b c
0 0.0 10.0 7.0
1 11.0 10.0 NaN
2 2.0 14.0 NaN
3 11.0 NaN NaN
问题11
之后如何将多个索引展平为单个索引pivot
If columns
type object
带绳子join
df.columns = df.columns.map('|'.join)
else format
df.columns = df.columns.map('{0[0]}|{0[1]}'.format)