加载列数不均的文本文件至NumPy数组时遇错误的技术问询
解决NumPy导入列数不均文本数据的问题
嘿,这个场景我太熟了——不规则列的文本数据确实会让NumPy的常规loadtxt或者genfromtxt直接报错,毕竟NumPy天生就需要规整的数组结构。针对你150k行的数据集,给你几个实用的解决方案,按需选择就行:
方案1:使用NumPy结构化数组(保留原始数据结构)
如果需要完整保留每个样本的所有国家代码,不做填充,结构化数组是最佳选择,它允许不同列有不同的数据类型,甚至可以存可变长度的对象。
import numpy as np # 逐行读取并预处理数据 processed_rows = [] with open('your_data.txt', 'r') as f: for line in f: # 去掉行尾的$和换行符 cleaned_line = line.strip().rstrip('$') # 拆分每行内容 parts = cleaned_line.split() # 提取各部分数据 gender = parts[0] name = parts[1] country_codes = list(map(int, parts[2:])) # 把当前行的数据加入列表 processed_rows.append( (gender, name, country_codes) ) # 定义结构化数组的数据类型 dtype_spec = [ ('gender', 'U1'), # 性别:1个字符的Unicode字符串 ('name', 'U30'), # 姓名:最长30个字符的Unicode字符串 ('country_codes', 'O') # 国家代码:对象类型,用来存储列表/数组 ] # 转换为NumPy结构化数组 structured_array = np.array(processed_rows, dtype=dtype_spec)
优点:
- 完全保留原始数据,没有冗余填充值
- 可以直接通过字段名访问数据,比如
structured_array['name']获取所有姓名
方案2:填充为规整的二维数组(适合数值运算)
如果后续需要对国家代码做批量数值运算,规整的二维数组会更方便。先找出所有行中国家代码的最大数量,用默认值(比如0或NaN)填充到统一长度:
import numpy as np # 第一步:遍历所有行,确定国家代码的最大数量 max_code_count = 0 all_raw_rows = [] with open('your_data.txt', 'r') as f: for line in f: cleaned_line = line.strip().rstrip('$') parts = cleaned_line.split() # 计算当前行的国家代码数量(总列数-2:去掉性别和姓名) current_code_count = len(parts) - 2 if current_code_count > max_code_count: max_code_count = current_code_count all_raw_rows.append(parts) # 第二步:将每行数据填充到统一长度 processed_data = [] fill_value = 0 # 如果国家代码没有0,用这个很安全;否则可以用np.nan(需转float类型) for parts in all_raw_rows: gender = parts[0] name = parts[1] codes = list(map(int, parts[2:])) # 填充到最大长度 padded_codes = codes + [fill_value] * (max_code_count - len(codes)) processed_data.append( [gender, name] + padded_codes ) # 转换为NumPy数组 # 注意:因为混合了字符串和整数,数组类型会是object;也可以拆分字符串和数值部分 full_array = np.array(processed_data, dtype=object) # 拆分出数值部分的数组(纯整数) country_code_array = np.array([row[2:] for row in processed_data], dtype=int)
优点:
- 得到规整的二维数组,方便后续做矩阵运算、统计分析
- 数值部分单独提取后可以用NumPy的所有数值工具
方案3:用Pandas预处理再转NumPy(高效省心)
对于150k行这种中等规模的数据,Pandas处理不规则列的效率和便捷性都拉满,它会自动处理缺失值,之后再转成NumPy格式也很简单:
import pandas as pd import numpy as np # 读取文本数据,自动拆分列,忽略行尾的$ df = pd.read_csv('your_data.txt', sep=' ', header=None, engine='python') # 删掉最后一列(全是$) df = df.iloc[:, :-1] # 方法A:转成规整的数值数组(自动补NaN) country_code_array = df.iloc[:, 2:].to_numpy(dtype=float) # 用float存NaN # 方法B:转成包含可变长度代码列表的结构化数组 df['country_codes'] = df.iloc[:, 2:].apply(lambda x: x.dropna().astype(int).tolist(), axis=1) structured_array = df[[0, 1, 'country_codes']].to_records(index=False) # 重命名字段(可选) structured_array.dtype.names = ('gender', 'name', 'country_codes')
优点:
- 代码量最少,Pandas自动处理所有拆分和缺失值逻辑
- 150k行数据读取和处理速度非常快,比手动逐行遍历效率高
小提示:
如果你的国家代码数量差异极大(比如有的行1个,有的行10个以上),填充方案会浪费内存,这时候优先选结构化数组或者Pandas的列表列方案,更节省空间。
内容的提问来源于stack exchange,提问作者Raady
相关产品推荐
相关产品推荐

