多加密货币多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
相关产品推荐
相关产品推荐

