|
|
1
Mykola Zotko
5 年前
我们先回答第一个问题:
为什么我会
ValueError: Index contains duplicate entries, cannot reshape
columns
index
具有重复项的对象。可以使用不同的方法来执行透视。它们中的一些不太适合在有重复的键的情况下被要求旋转。例如。考虑
pd.DataFrame.pivot
row
和
col
df.duplicated(['row', 'col']).any()
True
pivot
使用
df.pivot(index='row', columns='col', values='val0')
我得到上面提到的错误。事实上,当我尝试执行相同的任务时,我会遇到相同的错误:
df.set_index(['row', 'col'])['val0'].unstack()
下面是一个我们可以用来支点的习语列表
-
pd.DataFrame.groupby
+
pd.DataFrame.unstack
-
很好的一般方法做任何类型的枢轴
-
unstack
要在列索引中的级别。
-
pd.DataFrame.pivot_table
-
pd.DataFrame.set_index
+
-
方便和直观的一些(包括我自己)。无法处理重复的分组键。
-
类似于
子句
-
pd.DataFrame.pivot
-
非常类似于
set_index
因为它共享重复密钥限制。API也非常有限。它只需要标量值
指数
柱
values
.
-
类似于
pivot_table
方法中,我们选择要透视的行、列和值。但是,我们无法聚合,如果行或列不唯一,此方法将失败。
-
pd.crosstab
-
这是
数据透视表
在它最纯粹的形式是最直观的方式来执行几个任务。
-
pd.factorize
np.bincount
-
pd.get_dummies
+
pd.DataFrame.dot
示例
我接下来要做的是用
. 然后我将提供执行相同任务的替代方案。
问题3
我该如何旋转
df
列
值是列,
行
值是指
val0
是值,缺少的值是
0
?
-
pd.DataFrame.pivot\表
-
fill_value
默认情况下不设置。我倾向于适当地设置它。在这种情况下,我把它设置为
. 注意我跳过了
问题2
填充\u值
-
aggfunc='mean'
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.交叉表
pd.crosstab(
index=df['row'], columns=df['col'],
values=df['val0'], aggfunc='mean').fillna(0)
问题4
mean
sum
?
-
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.交叉表
pd.crosstab(
index=df['row'], columns=df['col'],
values=df['val0'], aggfunc='sum').fillna(0)
我可以一次多做一次聚合吗?
注意,对于
数据透视表
和
crosstab
groupby.agg
能够为有限数量的特殊函数获取字符串。
groupby.agg
也可以使用我们传递给其他人的相同的可调用函数,但是利用字符串函数名通常更有效,因为这样可以提高效率。
-
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.交叉表
pd.crosstab(
index=df['row'], columns=df['col'],
values=df['val0'], aggfunc=[np.size, np.mean]).fillna(0, downcast='infer')
我可以聚合多个值列吗?
-
我们通过了
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
可以按多列细分吗?
-
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\表
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)
-
因为键集对于行和列都是唯一的
df.set_index(
['key', 'row', 'item', 'col']
)['val0'].unstack(['item', 'col']).fillna(0).sort_index(1)
问题9
我是否可以聚合列和行同时出现的频率,即“交叉制表”?
-
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.交叉表
pd.crosstab(df['row'], df['col'])
-
pd.因式分解
+
np.bin计数
# 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(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
柱?
第一步是为每一行分配一个数字-该数字将是数据透视结果中该值的行索引。这是通过使用
GroupBy.cumcount
:
df2.insert(0, 'count', df.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(*df)
# df.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
问题11
之后如何将多个索引展平为单个索引
枢轴
如果
柱
类型
object
带字符串
join
df.columns = df.columns.map('|'.join)
其他的
format
df.columns = df.columns.map('{0[0]}|{0[1]}'.format)
|