如何清洗DataFrame列中重复格式内容并重构参数-值-单位结构?
清洗CSV格式实验数据并重塑DataFrame的解决方案
我明白你现在的需求——把每列都是“参数名 is 数值 单位”格式的原始DataFrame,转换成以参数为第一列、各列对应数值为后续列、最后加单位列的新结构。你之前尝试的split方法没达到效果,是因为只处理了单列的拆分,没完成整个DataFrame的重塑和多列的整合,我来给你两种可行的解决思路:
方法一:自定义拆分函数+批量处理
这种方法逻辑直观,适合你当前列数不多的场景:
首先,我们先定义一个辅助函数,用来拆分每个单元格里的文本,提取出参数、数值和单位:
import pandas as pd # 原始数据 df = pd.DataFrame({ 'rev45s':['Area is 389.62 km^2','aspArea is 76.61 km^2','asp_Ave_slip is 1.59 m','Mw is 5.5'], 'rev45':['Area is 589.32 km^2','aspArea is 66.65 km^2','asp_Ave_slip is 3.69 m','Mw is 6.1'], 'SS45':['Area is 319.62 km^2','aspArea is 61.71 km^2','asp_Ave_slip is 3.09 m','Mw is 6.8'], 'SS45s':['Area is 489.52 km^2','aspArea is 54.61 km^2','asp_Ave_slip is 1.44 m','Mw is 9.5'] }) def parse_text(text): parts = text.split(' ') param = parts[0] # 把数值转成浮点型方便后续分析 value = float(parts[2]) # Mw没有单位,所以判断拆分后的元素数量 unit = parts[3] if len(parts) == 4 else '-' return param, value, unit # 对每一列批量提取参数、数值、单位 rev45s_params, rev45s_values, rev45s_units = zip(*df['rev45s'].apply(parse_text)) rev45_params, rev45_values, rev45_units = zip(*df['rev45'].apply(parse_text)) SS45_params, SS45_values, SS45_units = zip(*df['SS45'].apply(parse_text)) SS45s_params, SS45s_values, SS45s_units = zip(*df['SS45s'].apply(parse_text)) # 构建目标DataFrame new_df = pd.DataFrame({ 'parameter': rev45s_params, 'rev45s_value': rev45s_values, 'rev45_value': rev45_values, 'SS45_value': SS45_values, 'SS45s_value': SS45s_values, 'unit': rev45s_units }) print(new_df)
运行后就能得到你需要的结构,参数列、各列数值、单位列都清晰分开。
方法二:利用melt+正则提取(更灵活)
如果后续你的列数会增加,这种方法扩展性更好,不用手动处理每一列:
import pandas as pd # 原始数据同上 df = pd.DataFrame({ 'rev45s':['Area is 389.62 km^2','aspArea is 76.61 km^2','asp_Ave_slip is 1.59 m','Mw is 5.5'], 'rev45':['Area is 589.32 km^2','aspArea is 66.65 km^2','asp_Ave_slip is 3.69 m','Mw is 6.1'], 'SS45':['Area is 319.62 km^2','aspArea is 61.71 km^2','asp_Ave_slip is 3.09 m','Mw is 6.8'], 'SS45s':['Area is 489.52 km^2','aspArea is 54.61 km^2','asp_Ave_slip is 1.44 m','Mw is 9.5'] }) # 第一步:把宽格式转成长格式,方便统一处理所有文本 melted = df.melt(var_name='column', value_name='text') # 第二步:用正则表达式批量提取参数、数值、单位 # 正则匹配规则:匹配开头的参数(支持带下划线的),然后是" is ",接着是数值,最后可选的单位 melted[['parameter', 'value', 'unit']] = melted['text'].str.extract( r'^(\w+_\w+|\w+) is ([\d.]+)(?: (\w+\^?\w+))?$', expand=True ) # 处理Mw的单位为空的情况,替换成'-' melted['unit'] = melted['unit'].fillna('-') # 把数值转成浮点型 melted['value'] = melted['value'].astype(float) # 第三步:把长格式转回宽格式,得到各列的数值 new_df = melted.pivot(index='parameter', columns='column', values='value').reset_index() # 重命名列名,符合你的需求 new_df.columns = ['parameter', 'rev45s_value', 'rev45_value', 'SS45_value', 'SS45s_value'] # 添加单位列:因为每个参数的单位是统一的,所以提取唯一映射关系 unit_map = melted.drop_duplicates('parameter').set_index('parameter')['unit'].to_dict() new_df['unit'] = new_df['parameter'].map(unit_map) print(new_df)
为什么你之前的方法无效?
你之前用df['rev45s']=df['rev45s'].apply(lambda x: pd.Series(x.split()))或者str.split,只是把单列的文本拆成了列表/多列,但没有把提取出的参数、数值、单位对应到整个新DataFrame的结构里,相当于只做了单列的拆分,没有完成跨列的整合和结构重塑,所以达不到目标。
内容的提问来源于stack exchange,提问作者sam_sam
相关产品推荐
相关产品推荐

