You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用pd.pivot_table转换数据时出现NaN值的原因及解决方法

问题:使用pd.pivot_table转换真实数据时出现大量NaN值的原因与解决办法

背景

我是Python新手,想用pd.pivot_table把数据从长格式转成宽格式。示例数据转换一切正常,但用到真实数据时结果里出现了大量NaN,想知道原因和解决方法。

示例数据与成功代码

示例长格式数据

TimeStamp [us] Source Channel Label Value [pV] Spike
0              1                   A1          0     0
1              2                   A1      -1400     1
2              3                   A1          0     0
3              1                   B1      -1400     1
4              2                   B1          0     0
5              3                   B1          0     0

期望的宽格式结果

TimeStamp [us]          1    2    3
Source Channel Label               
A1                    0.0  1.0  0.0
B1                    1.0  0.0  0.0

可复现的成功代码

# 构造示例数据
example_1 = {'TimeStamp [us]': ["1", "2", "3", "1", "2", "3"],
            'Source Channel Label': ["A1", "A1", "A1","B1", "B1", "B1"],
            'Value [pV]': ["0", "-1400", "0","-1400", "0", "0"],
            'Spike': ["0", "1", "0", "1","0", "0"]}

# 转为DataFrame
example_1 = pd.DataFrame(example_1)

# 转换为宽格式 - 运行正常
example_wide = pd.pivot_table(example_1, index='Source Channel Label', columns='TimeStamp [us]', values='Spike')

print(example_wide)

真实数据遇到的问题

真实长格式数据

TimeStamp [µs] Source Channel Label  Value [pV]  Spike
0              402600                  F10           0    0.0
1              402700                  F10           0    0.0
2              402800                  F10           0    0.0
3              402900                  F10           0    0.0
4              403000                  F10     -149012    1.0
              ...                  ...         ...    ...
845142      299700800                  G10           0    0.0
845143      299700900                  G10           0    0.0
845144      299701000                  G10           0    0.0
845145      299701100                  G10           0    0.0
845146      299701200                  G10           0    0.0

[825902 rows x 4 columns]

转换代码

week6_233C_1_wide = pd.pivot_table(week6_233C_1, index='Source Channel Label', columns='TimeStamp [µs]', values='Spike')

转换结果(含大量NaN)

TimeStamp [µs]        1000  10000  100000  ...  99999300  99999400  99999500
Source Channel Label                       ...                               
A1                     NaN    NaN     NaN  ...       NaN       NaN       NaN
A10                    NaN    NaN     NaN  ...       0.0       0.0       0.0
A2                     NaN    NaN     NaN  ...       NaN       NaN       NaN
A3                     NaN    NaN     NaN  ...       NaN       NaN       NaN
A4                     NaN    NaN     NaN  ...       NaN       NaN       NaN
                   ...    ...     ...  ...       ...       ...       ...
M5                     NaN    NaN     NaN  ...       NaN       NaN       NaN
M6                     NaN    NaN     NaN  ...       NaN       NaN       NaN
M7                     NaN    NaN     NaN  ...       NaN       NaN       NaN
M8                     NaN    NaN     NaN  ...       NaN       NaN       NaN
M9                     NaN    NaN     NaN  ...       NaN       NaN       NaN

[114 rows x 528921 columns]

原因分析

  1. 时间戳范围不重叠:示例数据里每个通道都覆盖了所有时间戳,但真实数据中不同通道的时间戳是分段的(比如F10的时间戳从402600开始,G10到299701200,A1的时间戳可能在另一区间),pivot后没有对应数据的位置就会填充NaN。
  2. 数据点缺失:部分通道在某些时间点没有采集记录,自然会出现NaN。
  3. 重复数据影响(可能):如果同一通道同一时间戳有重复数据,pivot_table默认用mean聚合,也可能导致异常值或NaN。

解决方法

方法1:直接填充NaN为默认值

如果NaN代表该时间点没有Spike(即Spike=0),用fillna一键填充:

week6_233C_1_wide = pd.pivot_table(week6_233C_1, index='Source Channel Label', columns='TimeStamp [µs]', values='Spike').fillna(0)

方法2:补全所有通道的时间序列

如果需要每个通道都拥有完整的全局时间戳范围,先补全缺失时间点再转宽格式:

# 获取所有唯一的时间戳
all_timestamps = week6_233C_1['TimeStamp [µs]'].unique()

# 给每个通道补全时间戳,缺失的Spike填0
def fill_channel_timestamps(group):
    group = group.set_index('TimeStamp [µs]')
    group = group.reindex(all_timestamps, fill_value=0)
    return group['Spike']

# 分组处理后转宽格式
week6_233C_1_wide = week6_233C_1.groupby('Source Channel Label').apply(fill_channel_timestamps).unstack()

方法3:处理重复数据并指定聚合方式

先检查是否有重复的(通道+时间戳)组合,然后指定聚合规则:

# 检查重复数据数量
duplicate_count = week6_233C_1.duplicated(subset=['Source Channel Label', 'TimeStamp [µs]']).sum()
print(f"重复数据条数:{duplicate_count}")

# 用first取第一条数据,或者sum求和,同时填充NaN为0
week6_233C_1_wide = pd.pivot_table(week6_233C_1, 
                                   index='Source Channel Label', 
                                   columns='TimeStamp [µs]', 
                                   values='Spike', 
                                   aggfunc='first').fillna(0)

内容的提问来源于stack exchange,提问作者Celine Serry

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 02:09:52