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

从DataFrame拆分账户名与卡号列:groupby方法失效求助

问题:拆分DataFrame中的账户名与卡号列

需要将包含Account / Card、Balance Start、Balance End、Difference列的DataFrame,把Account / Card列拆分为账户名和卡号两列。原DataFrame数据如下:

Account / Card  Balance Start  Balance End  Difference
0            MASTER         701.00       701.00        0.00
0               NaN            NaN          NaN         NaN
1   Algemeen/*!%@!#        2240.25      2181.45      -58.80
9         120989894           0.00         0.00        0.00
5         159142752           0.00         0.00        0.00
4         286695535         300.00       300.00        0.00
12        578951057          30.00        30.00        0.00
13        706602827           0.00         0.00        0.00
2         735592139           0.00         0.00        0.00
11        810226753         250.00       229.16      -20.84
3         811695012           0.00         0.00        0.00
6         818329167          22.85        22.85        0.00
0               NaN            NaN          NaN         NaN
2           General        3913.56      3813.56     -100.00
8         138738399          42.79        27.79      -15.00
0         646746507           0.00         0.00        0.00
1         767402418           2.90         2.90        0.00
10        948214665         545.07       391.57     -153.50
7         A98744534         461.32        75.36     -385.96
0               NaN            NaN          NaN         NaN
0            Totals        8509.74      7775.64     -734.10

尝试了以下groupby代码但未达到预期效果:

for date, new_df in balances.groupby(level=0):
    print(new_df)

解决方案1:基于空行分组(贴合原数据结构)

原数据用全空行分隔不同账户组,每个组的第一行是账户名,下方为该账户的卡号。可以按此规则分组处理:

import pandas as pd
import numpy as np

# 标记全空行
balances['is_empty_row'] = balances.isna().all(axis=1)
# 生成分组ID:每遇到一个空行,分组ID递增
balances['group_id'] = balances['is_empty_row'].cumsum()
# 过滤空行和总计行
filtered_df = balances[~balances['is_empty_row'] & (balances['Account / Card'] != 'Totals')].copy()

# 为每个分组拆分账户名和卡号
def process_group(group):
    # 每组第一行是账户名
    account_name = group.iloc[0]['Account / Card']
    group['Account Name'] = account_name
    # 卡号列:仅保留非账户名的行
    group['Card Number'] = np.where(group.index == group.index[0], np.nan, group['Account / Card'])
    return group

# 分组处理并整理结果
result_df = filtered_df.groupby('group_id').apply(process_group)
result_df = result_df.drop(columns=['is_empty_row', 'group_id']).reset_index(drop=True)
# 移除账户名行(卡号为NaN的行)
result_df = result_df.dropna(subset=['Card Number']).reset_index(drop=True)

# 输出最终结构
print(result_df[['Account Name', 'Card Number', 'Balance Start', 'Balance End', 'Difference']])

解决方案2:基于内容规则识别

如果空行分隔不固定,可通过内容特征区分账户名和卡号:账户名包含字母/特殊字符,卡号为纯数字或带前缀的类卡号格式:

import pandas as pd
import numpy as np

# 识别账户名行:非纯数字字符串,且不是总计行
def is_account_name(x):
    if not isinstance(x, str) or x == 'Totals':
        return False
    # 移除特殊字符后判断是否为纯数字,非纯数字则为账户名
    cleaned = x.replace('/*!%@!#', '')
    return not cleaned.isdigit()

balances['is_account'] = balances['Account / Card'].apply(is_account_name)

# 向前填充账户名,为每行匹配所属账户
balances['Account Name'] = balances.loc[balances['is_account'], 'Account / Card'].ffill()

# 提取卡号列:非账户名行的Account/Card值
balances['Card Number'] = np.where(balances['is_account'], np.nan, balances['Account / Card'])

# 过滤空行、账户名行和总计行
result_df = balances[
    ~balances['is_account'] 
    & ~balances['Account / Card'].isna() 
    & (balances['Account / Card'] != 'Totals')
].copy()

# 整理最终列顺序
result_df = result_df[['Account Name', 'Card Number', 'Balance Start', 'Balance End', 'Difference']].reset_index(drop=True)

print(result_df)

内容的提问来源于stack exchange,提问作者Talha Shafique

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 20:40:34