Python/Pandas按行内指定位置拆分字符串列的技术实现问题
按每行指定规则拆分Pandas DataFrame的字符串列
有一个Pandas DataFrame,包含campaign_name列,内容是按规则生成的字符串;同时还有separator(分隔符)、SKU、CAMPAIGN、GOAL、FORMAT列,记录每行字符串的分隔符,以及各信息对应的拆分后位置。比如第一行里,字符串用下划线分隔,SKU对应拆分后的第0位,CAMPAIGN对应第1位,GOAL对应第2位。现在要按每行指定的位置拆分campaign_name列,但当前代码无法实现需求。
示例DataFrame
results = pd.DataFrame([{'data': '2022-01-01' , 'canal': 'Facebook/Instagram' , 'campaign_name': 'SKU098_COMMERCIALCAMPAIGN_VIEW' , 'Cost': 1.5 , 'separator': '_' , 'SKU': 0, 'CAMPAIGN': 1, 'GOAL': 2, 'FORMAT': 100}, {'data': '2019-01-01' , 'canal': 'Facebook/Instagram' , 'campaign_name': 'NEWYEAR_REACH_SKU4354' , 'Cost': 0.4 , 'separator': '_' , 'SKU': 2, 'CAMPAIGN': 0, 'GOAL': 1, 'FORMAT': 100}, {'data': '2022-01-09' , 'canal': 'Facebook/Instagram' , 'campaign_name': 'VIDEO_REACH_SKU4354' , 'Cost': 2.1 , 'separator': '_' , 'SKU': 2, 'CAMPAIGN': 100, 'GOAL': 1, 'FORMAT': 0}, {'data': '2022-08-20' , 'canal': 'Facebook/Instagram' , 'campaign_name': 'INTERATIONS/SKU2134/CHRISTMAS' , 'Cost': 1.2 , 'separator': '/' , 'SKU': 1, 'CAMPAIGN': 2, 'GOAL': 0, 'FORMAT': 100} ]) print(results)
当前尝试的代码
results['SKU_2'] = results['campaign_name'].str.split(results['separator']).str[results['SKU']]
期望结果
data canal campaign_name Cost separator SKU CAMPAIGN GOAL FORMAT 0 2022-01-01 Facebook/Instagram SKU098_COMMERCIALCAMPAIGN_VIEW 1.5 _ SKU098 COMMERCIALCAMPAIGN VIEW NaN 1 2019-01-01 Facebook/Instagram NEWYEAR_REACH_SKU4354 0.4 _ SKU4354 NEWYEAR REACH NaN 2 2022-01-09 Facebook/Instagram VIDEO_REACH_SKU4354 2.1 _ SKU4354 NaN REACH VIDEO 3 2022-08-20 Facebook/Instagram INTERATIONS/SKU2134/CHRISTMAS 1.2 / SKU2134 CHRISTMAS INTERATIONS NaN
解决方案
原来的代码行不通是因为str.split没法直接接收Series作为分隔符参数,而且str[]也不能按行取不同的索引值。这里提供两种可行的方法:
方法一:用apply逐行处理
这是最直观的方式,逐行拆分字符串并提取对应位置的内容:
import pandas as pd def process_row(row): # 按当前行的分隔符拆分字符串 parts = row['campaign_name'].split(row['separator']) # 提取各字段,索引超出范围则设为NaN row['SKU'] = parts[row['SKU']] if row['SKU'] < len(parts) else pd.NA row['CAMPAIGN'] = parts[row['CAMPAIGN']] if row['CAMPAIGN'] < len(parts) else pd.NA row['GOAL'] = parts[row['GOAL']] if row['GOAL'] < len(parts) else pd.NA row['FORMAT'] = parts[row['FORMAT']] if row['FORMAT'] < len(parts) else pd.NA return row # 应用到每行 results = results.apply(process_row, axis=1) print(results)
方法二:预拆分后批量提取
先拆分所有行的字符串,再批量匹配索引取值,大数据量下效率稍高:
import pandas as pd # 先拆分所有行的campaign_name,得到包含拆分后列表的Series split_parts = results.apply(lambda x: x['campaign_name'].split(x['separator']), axis=1) # 需要处理的字段列表 fields = ['SKU', 'CAMPAIGN', 'GOAL', 'FORMAT'] # 逐个字段提取对应位置的内容 for field in fields: results[field] = [ parts[idx] if idx < len(parts) else pd.NA for parts, idx in zip(split_parts, results[field]) ] print(results)
两种方法都能得到符合期望的结果,核心逻辑都是确保每行的分隔符和索引一一对应,同时处理索引超出范围的情况(比如值为100时返回NaN)。
内容的提问来源于stack exchange,提问作者laosnd
相关产品推荐
相关产品推荐

