Skip to main content
 首页 » 编程设计

python之用于热图的 pandas 数据透视表

2025年05月04日23lexus

我正在尝试使用 seaborn 生成热图,但是我的数据格式存在一个小问题。

目前,我的数据是这样的:

Name     Diag   Date 
A        1       2006-12-01 
A        1       1994-02-12 
A        2       2001-07-23 
B        2       1999-09-12 
B        1       2016-10-12 
C        3       2010-01-20 
C        2       1998-08-20 

我想创建一个热图(最好是在 python 中),在一个轴上显示 Name 与 Diag - 如果发生的话。我曾尝试使用 pd.pivot 旋转表格,但出现错误

ValueError: Index contains duplicate entries, cannot reshape

这来自:

piv = df.pivot_table(index='Name',columns='Diag')

时间无关紧要,但我想展示哪些 Names 有哪些 Diag,以及哪些 Diag 组合在一起。我是否需要为此创建一个新表,或者我有可能创建一个新表吗?在某些情况下,Name 并未与所有 Diag

相关联

编辑: 从那以后我尝试过: piv = df.pivot_table(index='Name',columns='Diag', values='Time', aggfunc='mean')

然而,由于时间是日期时间格式,我最终得到:
pandas.core.base.DataError: No numeric types to aggregate

请您参考如下方法:

你需要pivot_table使用一些聚合函数,因为对于相同的索引和列有多个值,pivot 只需要唯一值:

print (df) 
  Name  Diag  Time 
0    A     1    12 <-duplicates for same A, 1 different value 
1    A     1    13 <-duplicates for same A, 1 different value 
2    A     2    14 
3    B     2    18 
4    B     1     1 
5    C     3     9 
6    C     2     8 
 
df = df.pivot_table(index='Name',columns='Diag', values='Time', aggfunc='mean') 
print (df) 
Diag     1     2    3 
Name                  
A     12.5  14.0  NaN 
B      1.0  18.0  NaN 
C      NaN   8.0  9.0 

替代方案:

df = df.groupby(['Name','Diag'])['Time'].mean().unstack() 
print (df) 
Diag     1     2    3 
Name                  
A     12.5  14.0  NaN 
B      1.0  18.0  NaN 
C      NaN   8.0  9.0 

编辑:

您还可以通过 duplicated 检查所有重复项:

df = df.loc[df.duplicated(['Name','Diag'], keep=False), ['Name','Diag']] 
print (df) 
  Name  Diag 
0    A     1 
1    A     1 

编辑:

日期时间的

mean 并不容易 - 需要将日期转换为 nanoseconds,获取平均值并最后转换为日期时间。还有另一个问题 - 需要将 NaN 替换为一些标量,例如0 转换为 0 日期时间 - 1970-01-01。

df.Date = pd.to_datetime(df.Date) 
df['dates_in_ns'] = pd.Series(df.Date.values.astype(np.int64), index=df.index) 
df = df.pivot_table(index='Name', 
                    columns='Diag',  
                    values='dates_in_ns',  
                    aggfunc='mean',  
                    fill_value=0) 
df = df.apply(pd.to_datetime) 
print (df) 
Diag                   1          2          3 
Name                                           
A    2000-07-07 12:00:00 2001-07-23 1970-01-01 
B    2016-10-12 00:00:00 1999-09-12 1970-01-01 
C    1970-01-01 00:00:00 1998-08-20 2010-01-20