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

多加密货币多K线周期合并DataFrame时出现NaN值如何解决

问题根因

你出现大量NaN的核心原因是:每次生成的单币种单周期DataFrame的列都是唯一的元组键,和其他币种/周期的列无重叠,且行索引默认从0开始自增,调用append按行拼接时,非当前币种周期的列没有对应值,就会自动填充NaN。

下面提供3种可行方案,你可以根据自己的使用场景选择:


方案1:字典单独存储各币种周期数据(最省心,无NaN)

适合不需要跨币种周期批量运算的场景,直接用币种/周期作为key存储对应DataFrame,后续取用、增量更新都不会出现混淆,完全不会产生NaN。

import pandas as pd
from binance.client import Client

symbols = ['ETHUSDT','BTCUSDT']
intervals = ['30m','1h']

api_secret = '替换为你的api_secret'
api_key = '替换为你的api_key'
client = Client(api_key, api_secret)

# 字典key格式为 币种/周期,比如BTCUSDT/1h
kline_data = {}
for interval in intervals:
    for symbol in symbols:
        key = f"{symbol}/{interval}"
        historical = client.get_historical_klines(symbol, interval, '11/16/2021', limit=1000)[-4:]
        df = pd.DataFrame(historical)
        df.drop([6,7,8,9,10,11], axis=1, inplace=True)
        df.columns = ['time', 'open', 'high', 'low', 'close', 'volume']
        # 时间戳转datetime格式方便后续处理
        df['time'] = pd.to_datetime(df['time'], unit='ms')
        kline_data[key] = df

# 取用示例:获取BTCUSDT的1小时K线数据
btc_1h_df = kline_data['BTCUSDT/1h']
# 增量更新示例:新拉取1条数据后追加
# new_kline = 新获取的单条K线数据转成的df
# kline_data['BTCUSDT/1h'] = pd.concat([kline_data['BTCUSDT/1h'], new_kline], ignore_index=True)

方案2:长表结构存储总DataFrame(适合批量查询运算,无NaN)

所有数据存在同一张总表,新增symbol和interval两个标识列,后续查询用筛选条件即可,完全不会产生NaN,增量更新逻辑也非常简单。

import pandas as pd
from binance.client import Client

symbols = ['ETHUSDT','BTCUSDT']
intervals = ['30m','1h']

api_secret = '替换为你的api_secret'
api_key = '替换为你的api_key'
client = Client(api_key, api_secret)

total_df = pd.DataFrame()
for interval in intervals:
    for symbol in symbols:
        historical = client.get_historical_klines(symbol, interval, '11/16/2021', limit=1000)[-4:]
        df = pd.DataFrame(historical)
        df.drop([6,7,8,9,10,11], axis=1, inplace=True)
        df.columns = ['time', 'open', 'high', 'low', 'close', 'volume']
        # 新增标识列区分币种和周期
        df['symbol'] = symbol
        df['interval'] = interval
        df['time'] = pd.to_datetime(df['time'], unit='ms')
        # 追加到总表
        total_df = pd.concat([total_df, df], ignore_index=True)

# 查询示例:筛选BTCUSDT的1小时K线数据
btc_1h_df = total_df[(total_df['symbol'] == 'BTCUSDT') & (total_df['interval'] == '1h')]
# 增量更新示例:新数据添加标识列后直接追加
# new_df = 新获取的K线数据df,提前添加好对应的symbol和interval列
# total_df = pd.concat([total_df, new_df], ignore_index=True)

方案3:保留MultiIndex列宽表(解决NaN问题)

如果你坚持要使用MultiIndex列的宽表结构,正确的拼接方式是先将每个单币种单周期df的时间列设为索引,列转为MultiIndex,再按列拼接,会自动按时间索引对齐,减少无效NaN。

import pandas as pd
from binance.client import Client

symbols = ['ETHUSDT','BTCUSDT']
intervals = ['30m','1h']

api_secret = '替换为你的api_secret'
api_key = '替换为你的api_key'
client = Client(api_key, api_secret)

df_list = []
for interval in intervals:
    for symbol in symbols:
        historical = client.get_historical_klines(symbol, interval, '11/16/2021', limit=1000)[-4:]
        df = pd.DataFrame(historical)
        df.drop([6,7,8,9,10,11], axis=1, inplace=True)
        df.columns = ['time', 'open', 'high', 'low', 'close', 'volume']
        df['time'] = pd.to_datetime(df['time'], unit='ms')
        # 设时间为索引
        df = df.set_index('time')
        # 列转为MultiIndex:[币种, 周期, 字段]
        df.columns = pd.MultiIndex.from_product([[symbol], [interval]], df.columns)
        df_list.append(df)

# 按列拼接,自动按时间索引对齐
total_wide_df = pd.concat(df_list, axis=1)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 10:15:01