首页 > 解决方案 > 带有重复条目的 Pandas 枢轴

问题描述

我正在尝试转换此数据框:

| project  | id | problem | result |
|----------|----|---------|--------|
| Project1 | 1  | P1      | True   |
| Project1 | 1  | P2      | True   |
| Project1 | 1  | P3      | False  |
| Project1 | 1  | P4      | True   |
| Project1 | 1  | P5      | NA     |
| Project2 | 1  | P1      | True   |
| Project2 | 1  | P2      | False  |
| Project2 | 1  | P3      | False  |
| Project2 | 1  | P4      | NA     |
| Project2 | 1  | P5      | True   |

对此:

| project  | id | P1   | P2    | P3    | P4   | P5   |
|----------|----|------|-------|-------|------|------|
| Project1 | 1  | True | True  | False | True | NA   |
| Project2 | 1  | True | False | False | NA   | True |

我尝试了枢轴方法:

df.pivot(index=["project", "id"], columns="problem", values="result")

但是,我收到了错误:ValueError: Index contains duplicate entries, cannot reshape

如何转换数据框?

标签: pythonpandas

解决方案


DataFrame.pivot_table与自定义 lambda 函数一起使用:

df = df.pivot_table(index=["project", "id"], 
                    columns="problem", 
                    values="result", 
                    aggfunc=lambda x: x.any() if x.notna().all() else np.nan)
print (df)
problem        P1     P2     P3    P4    P5
project  id                                
Project1 1   True   True  False  True   NaN
Project2 1   True  False  False   NaN  True

如果需要使用NaNs 和 booleanTrue/False可以使用Nullable Boolean 数据类型

df['result'] = df['result'].astype('boolean')

df = df.pivot_table(index=["project", "id"], 
                    columns="problem",
                    values="result", 
                    aggfunc=lambda x: x.any() if x.notna().all() else np.nan)
print (df)
problem        P1     P2     P3    P4    P5
project  id                                
Project1 1   True   True  False  True  <NA>
Project2 1   True  False  False  <NA>  True

如果可能,True/False仅输出:

df = df.pivot_table(index=["project", "id"], 
                    columns="problem",
                    values="result", 
                    aggfunc='any')
print (df)
problem        P1     P2     P3     P4     P5
project  id                                  
Project1 1   True   True  False   True  False
Project2 1   True  False  False  False   True

编辑:在熊猫 1.3+ 版本中可以使用:

df = df.pivot_table(index=["project", "id"], 
                    columns="problem",
                    values="result", 
                    aggfunc=lambda x: x.any(skipna=True))
print (df)

推荐阅读