Pandas处理含混合列表与范围的字典时的报错问题及解决方案咨询
Pandas处理含混合列表与范围的字典时的报错问题及解决方案咨询
我完全懂你现在的困扰——想保留原字典里的区间结构(混合range和列表),转成Pandas DataFrame时却因为列长度不匹配报错,连查询想要的值都做不了,确实挺头疼的!
先帮你理清楚问题根源:你的X-Raw列是4个区间/子列表(每个对应一段原始值范围),但1-8B和S-PP却是一整串连续的调整值,两者的元素数量完全不匹配(X-Raw只有4个元素,另外两列有几十个),Pandas转DataFrame时要求每一列的元素个数必须一致,这就是你看到ValueError: All arrays must be of the same length的原因。
下面给你两个兼顾保留原结构和解决查询需求的方案:
方案一:调整字典结构,让列元素长度匹配(保留原区间)
核心思路是把1-8B和S-PP的长列表,按照X-Raw里每个区间的长度,切成对应的子列表,这样整个字典的每一列都有4个元素(每个元素是一个子列表),就能顺利转成DataFrame了,而且完全保留你想要的区间结构。
具体代码如下:
import pandas as pd ScaleX_Adjustment = { 'X-Raw': [range(0, 34), list(range(34, 61)), range(61, 124), list(range(124, 179))], '1-8B': [+20, +20, +20, +20, +19, +18, +17, +17, +16, +15, +14, +13, +13, +12, +11, +10, +9, +9, +8, +7, +6, +5, +5, +4, +3, +2, +1, +1, 0, -1, -1, -1, -2, -2, -3, -3, -3, -4, -4, -5, -5, -5, -6, -6, -7, -7, -7, -8, -8, -9, -9 - 9, -10, -10, -11, -11, -11, -12, -12, -13, -13, -13, -14, -14, -15, -15, -15, -16, -16, -17, -17, -17, -18, -18, -19, -19, -19, -20, -20, -20, -20, -20, -20, -20], 'S-PP': [+10, +10, +10, +10, +10, +10, 9, 9, 9, 8, 8, 7, 7, 7, 6, 6, 5, 5, 5, 4, 4, 3, 3, 3, 2, 2, 1, 1, 0, -1, -1, -1, -2, -2, -2, -2, -2, -3, -3, -3, -3, -3, -4, -4, -4, -4, -4, -5, -5, -5, -5, -5, -6, -6, -6, -6, -6, -7, -7, -7, -7, -7, -8, -8, -8, -8, -8, -9, -9, -9, -9, -9, -10, -10, -10, -10, -10, -11, -11, -11, -11, -11, -11, -11] } # 第一步:把X-Raw里的range统一转成列表,方便后续处理 ScaleX_Adjustment['X-Raw'] = [list(r) if isinstance(r, range) else r for r in ScaleX_Adjustment['X-Raw']] # 第二步:计算每个X-Raw区间的长度,用来切割调整值列表 interval_lengths = [len(interval) for interval in ScaleX_Adjustment['X-Raw']] # 第三步:按区间长度切割1-8B和S-PP的长列表,生成对应子列表 start_idx = 0 adjusted_1_8B = [] adjusted_S_PP = [] for length in interval_lengths: adjusted_1_8B.append(ScaleX_Adjustment['1-8B'][start_idx:start_idx+length]) adjusted_S_PP.append(ScaleX_Adjustment['S-PP'][start_idx:start_idx+length]) start_idx += length # 更新字典,让所有列的元素数量一致 ScaleX_Adjustment['1-8B'] = adjusted_1_8B ScaleX_Adjustment['S-PP'] = adjusted_S_PP # 现在可以顺利转成DataFrame了 ScaleX_Adjustment_DF = pd.DataFrame(ScaleX_Adjustment)
针对查询需求的处理
转成DataFrame后,你可以写一个简单的函数,根据原始值ScaleX_Raw找到对应的调整值:
def get_adjustment_value(raw_num, df, column_name): # 遍历每一行,判断原始值是否在当前行的X-Raw区间里 for _, row in df.iterrows(): if raw_num in row['X-Raw']: # 找到该值在区间内的位置,返回对应调整值 pos_in_interval = row['X-Raw'].index(raw_num) return row[column_name][pos_in_interval] # 如果没找到匹配值,返回None或者按需抛出异常 return None # 示例使用 ScaleX_Raw = 50 ScaleX_1to8B = get_adjustment_value(ScaleX_Raw, ScaleX_Adjustment_DF, '1-8B') ScaleX_StoPP = get_adjustment_value(ScaleX_Raw, ScaleX_Adjustment_DF, 'S-PP')
方案二:保留原结构的同时,生成扁平DataFrame用于快速查询
如果你的查询需求比较频繁,上面的遍历方式效率不高,可以在保留原结构DataFrame的基础上,生成一个扁平的DataFrame(把所有区间展开成单条记录),用来快速查询:
def flatten_interval_df(original_df): flattened_rows = [] for _, row in original_df.iterrows(): # 把每个区间的原始值和对应调整值一一配对 for x_raw, adj_18b, adj_spp in zip(row['X-Raw'], row['1-8B'], row['S-PP']): flattened_rows.append({ 'X-Raw': x_raw, '1-8B': adj_18b, 'S-PP': adj_spp }) return pd.DataFrame(flattened_rows) # 生成扁平DataFrame flat_adjustment_df = flatten_interval_df(ScaleX_Adjustment_DF) # 快速查询,和你原来的写法几乎一致 ScaleX_1to8B = flat_adjustment_df.loc[flat_adjustment_df['X-Raw'] == ScaleX_Raw, '1-8B'].iloc[0] ScaleX_StoPP = flat_adjustment_df.loc[flat_adjustment_df['X-Raw'] == ScaleX_Raw, 'S-PP'].iloc[0]
这个方案的好处是:原结构的DataFrame用来保留你的区间逻辑,扁平DataFrame用来高效查询,两全其美。
备注:内容来源于stack exchange,提问作者Shreyas Balaji
相关产品推荐
相关产品推荐

