给定以下数据框:
results = pd.DataFrame({'Contractor':[1,1,0,0,0,1],
'President':[1,0,0,0,1,1],
'Item 1':[1,1,0,0,1,np.nan],
'Item 2':[1,0,0,1,0,1]})
results[['Contractor','President','Item 1','Item 2']]
results
Contractor President Item 1 Item 2
0 1 1 1 1
1 1 0 1 0
2 0 0 0 0
3 0 0 0 1
4 0 1 1 0
5 1 1 NaN 1
这供引用项目(见下文):
Position Item(s)
0 Contractor 1
1 President 1,2
...我想旋转数据以产生以下结果:
Position Overall%
0 Contractor 100
1 President 80
...基于这个逻辑:
由于总统关心第 1 项和第 2 项,因此需要考虑 5 个数字:第 1 项中的 (1 和 1) 以及第 2 项中的 (1, 0 和 1)。各个项目的总和 为 4,跨项目计数 为 5(不计算“NaN”),即 80%。
由于承包商只关心第 1 项,因此需要考虑 2 个数字:1 和 1 - 'NaN' 不应计算在内 - (分别来自感兴趣的行)。因此,总数为 2,即 2,即 100%
提前致谢!
最佳答案
import numpy as np
import pandas as pd
results = pd.DataFrame({'Contractor':[1,1,0,0,0,1],
'President':[1,0,0,0,1,1],
'Item 1':[1,1,0,0,1,np.nan],
'Item 2':[1,0,0,1,0,1]})
reference = pd.DataFrame({'Position':['Contractor','President'],
'Item(s)':[(1,), (1,2)]})
longref = pd.DataFrame([('Item {}'.format(item), row['Position'])
for index, row in reference.iterrows()
for item in row['Item(s)']], columns=['Item', 'Position'])
melted = pd.melt(results, id_vars=['Item 1','Item 2'], var_name='Position')
melted = melted.loc[melted['value']==1]
melted = pd.melt(melted, id_vars=['Position'],
value_vars=['Item 1','Item 2'], var_name='Item')
merged = pd.merge(longref, melted, how='left')
grouped = merged.groupby(['Position'])
result = (grouped['value'].sum() / grouped['value'].count())*100
result = result.rename('Overall%').reset_index()
print(result)
产量
Position Overall%
0 Contractor 100.0
1 President 80.0
说明:有一篇文章,作者:Hadley Wickham ( PDF ) 提出优点 使数据“整洁”。主要原则是每一行都应该 代表一个“观察”,每列代表一些因素或变量。
事实证明,您经常需要使用工具来表达您的计算 一旦数据整洁,就会很自然地就位。 这个问题的难度很大程度上来自于数据不整齐。
考虑结果
:
In [405]: results
Out[405]:
Contractor Item 1 Item 2 President
0 1 1.0 1 1
1 1 1.0 0 0
2 0 0.0 0 0
3 0 0.0 1 0
4 0 1.0 0 1
5 1 NaN 1 1
与其为 Contractor
和 President
设置单独的列,最好有一个名为 Position
的列,因为 Position
是变量,每个观察或行都可以有一个Position
值——Contractor
或President
。
同样,Item 1
和 Item 2
应合并为单列 Item
:
In [416]: melted
Out[416]:
Position Item value
0 Contractor Item 1 1.0
1 Contractor Item 1 1.0
2 Contractor Item 1 NaN
3 President Item 1 1.0
4 President Item 1 1.0
5 President Item 1 NaN
6 Contractor Item 2 1.0
7 Contractor Item 2 0.0
8 Contractor Item 2 1.0
9 President Item 2 1.0
10 President Item 2 0.0
11 President Item 2 1.0
melted
包含与 results
相同的信息,但格式简洁。 value
列包含 results[['Item 1', 'Item 2']]
中的值。每行对应一个“观察”,其中 results['Contractor']
或 result['President']` 等于 1,因为计算逻辑只需要这些值。
同样,代替
In [407]: reference
Out[407]:
Item(s) Position
0 (1,) Contractor
1 (1, 2) President
拥有一个列为 Item
和 Position
的 DataFrame 会更整洁:
In [408]: longref
Out[408]:
Item Position
0 Item 1 Contractor
1 Item 1 President
2 Item 2 President
一旦您获得了 melted
和 longref
形式的整洁数据版本,
计算所需的结果相当简单:
merged = pd.merge(longref, melted, how='left')
# Item Position value
# 0 Item 1 Contractor 1.0
# 1 Item 1 Contractor 1.0
# 2 Item 1 Contractor NaN
# 3 Item 1 President 1.0
# 4 Item 1 President 1.0
# 5 Item 1 President NaN
# 6 Item 2 President 1.0
# 7 Item 2 President 0.0
# 8 Item 2 President 1.0
grouped = merged.groupby(['Position'])
result = (grouped['value'].sum() / grouped['value'].count())*100
result = result.rename('Overall%').reset_index()
如何整理引用
以生成longref
:
只需迭代 reference
的行,并为每一行迭代项目元组以构建新的 DataFrame,longref
:
longref = pd.DataFrame([('Item {}'.format(item), row['Position'])
for index, row in reference.iterrows()
for item in row['Item(s)']], columns=['Item', 'Position'])
如何整理结果
以使融化
:
可以通过两次调用 pd.melt
来完成。 pd.melt
将“宽”格式转换为“长”格式 DataFrame。它可以将多个列合并为单个列。例如,要将承包商和总裁列合并为单个职位列,您可以使用:
melted = pd.melt(results, id_vars=['Item 1','Item 2'], var_name='Position')
# we only care about rows where Contractor or President value was 1. So use .loc to select those rows.
melted = melted.loc[melted['value']==1]
# Item 1 Item 2 Position value
# 0 1.0 1 Contractor 1
# 1 1.0 0 Contractor 1
# 5 NaN 1 Contractor 1
# 6 1.0 1 President 1
# 10 1.0 0 President 1
# 11 NaN 1 President 1
类似地,要将 Item 1
和 Item 2
列合并为单个 Item
列,请使用:
melted = pd.melt(melted, id_vars=['Position'],
value_vars=['Item 1','Item 2'], var_name='Item')
# Position Item value
# 0 Contractor Item 1 1.0
# 1 Contractor Item 1 1.0
# 2 Contractor Item 1 NaN
# 3 President Item 1 1.0
# 4 President Item 1 1.0
# 5 President Item 1 NaN
# 6 Contractor Item 2 1.0
# 7 Contractor Item 2 0.0
# 8 Contractor Item 2 1.0
# 9 President Item 2 1.0
# 10 President Item 2 0.0
# 11 President Item 2 1.0
关于python-3.x - 带有花式堆叠功能的 Pandas 数据透视表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37245338/