You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何清洗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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 21:12:38