如何在Pandas中去除单元格内空格分隔的重复值
问题描述
处理大规模数据(1500列、4000行)中单元格内的空格分隔重复值,保留第一个值并删除后续内容。部分单元格存在42.35 42.25 23.12这类格式,无法手动修复。
示例数据
PAG 0 54.36 1 50.3 2 46.81 3 47.71 4 42.35 42.35 <------ 此类存在重复值的单元格较多 5 43.91 6 43.54
数据结构及dtype信息
MthCalDt int64 A float64 AA float64 AAL float64 AAON float64 ... ZD float64 ZEN float64 ZION float64 ZTS float64 ZWS float64 Length: 1583, dtype: object
读取数据代码
cleaned_data = pd.read_csv("Wrds_Data\wrds_data_clean.csv") cleaned_data.head()
输出:
MthCalDt A AA AAL AAON AAP AAPL AAT AAWW AB ... YUMC YY Z ZBH ZBRA ZD ZEN ZION ZTS ZWS 0 20170131 48.97 36.45 44.25 33.95 164.24 121.35 42.93 52.75 23.35 ... 27.48 41.08 35.38 118.33 83.67 83.81 23.93 42.19 54.94 22.09 1 20170228 51.30 34.59 46.36 33.65 156.61 136.99 44.00 56.85 23.70 ... 26.59 44.29 33.94 117.08 90.71 81.42 27.23 44.90 53.31 22.17 2 20170331 52.87 34.40 42.30 35.35 148.26 143.66 41.84 55.45 22.85 ... 27.20 46.11 33.67 122.11 91.25 83.91 28.04 42.00 53.37 23.08 3 20170428 55.05 33.73 42.62 36.65 142.14 143.65 42.83 58.00 22.90 ... 34.12 48.97 39.00 119.65 94.27 90.24 28.75 40.03 56.11 24.40 4 20170531 60.34 32.94 48.41 36.18 133.63 152.76 39.05 48.70 22.55 ... 38.41 58.34 43.52 119.21 104.34 84.62 25.98 40.07 62.28 22.80
尝试过的方法及报错
方法1:直接转换类型+截取第一个值
cleaned_data = pd.read_csv("Wrds_Data\wrds_data_clean.csv") cleaned_data.astype(float) cleaned_data.applymap(lambda x: x.split(" ")[0])
报错:
could not convert string to float: '126.49 126.49' <--- 该单元格因含空格被识别为字符串
方法2:正则表达式替换
cleaned_data = pd.read_csv("Wrds_Data\wrds_data_clean.csv") columns = cleaned_data.columns.copy().drop('MthCalDt') cleaned_data[columns] = cleaned_data[columns].replace(r"^(\d+\.\d+) .*", r"\1", regex=True).astype(float) cleaned_data
报错:
Cell In [114], line 3 1 cleaned_data = pd.read_csv("Wrds_Data\wrds_data_clean.csv") 2 columns = cleaned_data.columns.copy().drop('MthCalDt') ----> 3 cleaned_data[columns] = cleaned_data[columns].replace(r"^(\d+\.\d+) .*", r"\1", regex=True).astype(float) 4 cleaned_data 169 # Explicit copy, or required since NumPy can't view from / to object. --> 170 return arr.astype(dtype, copy=True) 172 return arr.astype(dtype, copy=copy) ValueError: could not convert string to float: '60 55.66'
数据清洗步骤(供排查)
步骤1:原始数据格式
df1 = pd.read_csv("Wrds_Data\wrds_data_raw.csv")
输出:
Ticker MthCalDt MthPrc 0 JJSF 20170131 127.57 1 JJSF 20170228 133.8 2 JJSF 20170331 135.56 3 JJSF 20170428 134.58 4 JJSF 20170531 130.1
步骤2:转置宽表
df1 = pd.read_csv("Wrds_Data\wrds_data_raw.csv") df2 = df1.pivot_table(index='MthCalDt', columns="Ticker", values="MthPrc", aggfunc=lambda x: ' '.join(x.dropna())) df2.to_csv("Wrds_Data\wrds_data_clean.csv")
输出为宽表格式,部分单元格存在空格分隔的重复值。
解决方案
方案1:读取数据时直接处理(高效)
读取CSV时指定转换器,提前截取第一个值并转换类型:
import pandas as pd def extract_first_value(x): if pd.isna(x) or not isinstance(x, str): return x return float(x.split()[0]) # 获取需要处理的列(排除MthCalDt) cols = pd.read_csv("Wrds_Data\wrds_data_clean.csv", nrows=0).columns.drop('MthCalDt') converters = {col: extract_first_value for col in cols} cleaned_data = pd.read_csv("Wrds_Data\wrds_data_clean.csv", converters=converters)
方案2:读取后批量处理
兼容整数、小数形式的重复值,统一转字符串分割后取值:
cleaned_data = pd.read_csv("Wrds_Data\wrds_data_clean.csv") columns = cleaned_data.columns.drop('MthCalDt') cleaned_data[columns] = cleaned_data[columns].astype(str).str.split().str[0].astype(float)
方案3:从根源解决(转置时避免生成重复值)
在生成宽表阶段直接取第一个值,跳过拼接步骤:
df1 = pd.read_csv("Wrds_Data\wrds_data_raw.csv") # 用aggfunc='first'替代字符串拼接 df2 = df1.pivot_table(index='MthCalDt', columns="Ticker", values="MthPrc", aggfunc='first') df2.to_csv("Wrds_Data\wrds_data_clean.csv")
内容的提问来源于stack exchange,提问作者Trevor Seibert
相关产品推荐
相关产品推荐

