V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
cs1024
V2EX  ›  程序员

求助一个数据表处理的问题, sql, Python , R 都行

  •  
  •   cs1024 · 9 天前 · 641 次点击
    原始表
    id a1 a2 a3 b1 b2
    001 1 2 3 4 5
    002 6 7 8 9 10
    003 11 12 13 14 15

    期望输出
    id a b
    001 6 9
    002 21 19
    003 36 29

    其中 6=1+2+3 ,9=4+5

    数据转换逻辑:
    数据表 5000+字段,100w+行,
    新字段名 = 老字段名去除数字,
    新字段名的内容 = sum(老字段名的内容)


    不知道有没有简单的方法解决这个问题,
    感谢感谢~
    15 条回复    2024-06-17 22:16:38 +08:00
    NoOneNoBody
        1
    NoOneNoBody  
       9 天前
    sql : select a1+a2+a3 as a, b1+b2 as b from ...

    pandas:
    df['a'] = df[['a1', 'a2', 'a3']].sum(axis=1)
    df['b'] = df[['b1', 'b2']].sum(axis=1)
    result = df[['id', 'a', 'b']].copy()

    100w+不慢,用 numba 更快
    NoOneNoBody
        2
    NoOneNoBody  
       9 天前
    嗯,sql select 漏了 id ,自行补上
    cs1024
        3
    cs1024  
    OP
       9 天前
    @NoOneNoBody

    不仅仅 a1 a2 a3 b1 b2,,,
    实际有 5000+字段,
    而且字段名=字符串+数字,
    字符串和数字范围都是无规律的,

    直接硬编码太复杂了,
    lbaob
        4
    lbaob  
       9 天前
    python 里面,用 sql 语句获取表字段信息,然后根据字段生成 sql
    NoOneNoBody
        5
    NoOneNoBody  
       9 天前
    哦,漏看了,这样 dataframe 方便些

    mask =df.colums.str.starswith('a') # 这里是表示 a 开头,所以要确保没有其他无关的 a 开头字段名
    cols_a = df.colums[mask]
    df['a'] = df[cols_a].sum(axis=1)
    b 照样替换即可

    或者可以用正则
    mask = df.colums.str.contains(一个正则, case=False, regex=True)
    cols_a = df.colums[mask]
    NoOneNoBody
        6
    NoOneNoBody  
       9 天前
    #5 typo ,应是 columns
    NoOneNoBody
        7
    NoOneNoBody  
       9 天前
    再补充一下,用正则的话
    str.contains 是部分匹配,用 str.match 是整个字段名匹配,可以选择不同的方式和对应的正则
    也可以不用正则,参数改为 regex=False 即可
    cs1024
        8
    cs1024  
    OP
       9 天前
    @NoOneNoBody

    这个场景的难点就是 字段名 = 乱码 + 数字,
    而且字段很多,硬编码也得写 1000+次...
    NoOneNoBody
        9
    NoOneNoBody  
       9 天前
    @cs1024 #8
    问题是你也没有说清楚,给的例子也是最简单,谁看也不知道你的难点在哪啊

    你这个字段名有什么规律么,是否必然是字母或多个字母+数字,字符和数字两个是否分开
    然后,相同的字母组合,其数字是否必定是正整数,例如 1,2,3,4……顺序可以不对,但是否有缺的,如 1,2,4……
    只要有规律,自然可用正则来捕获
    pattern = r'^(?P<preffix>.+\D)?(?P<number>\d+)(?P<suffix>.+)?'
    类似这样的正则就能分开了,然后用 groupby 就能找到符合的一批字段名
    NoOneNoBody
        10
    NoOneNoBody  
       9 天前
    ```
    def groupedSimilarFilenames(filenames):
    '''
    将相似文件名分组\n
    输出类似格式\n
    filenames preffix suffix size \n
    0 cover.jpg NaN NaN 0 \n
    1 top.png NaN NaN 0 \n
    2 9.jpg NaN .jpg 0 \n
    3 015a.jpg 0 a.jpg 1 \n
    4 008.jpg 0 .jpg 9 \n
    5 010.jpg 0 .jpg 9 \n
    6 011.jpg 0 .jpg 9 \n
    7 012.jpg 0 .jpg 9 \n
    8 013.jpg 0 .jpg 9 \n
    9 014.jpg 0 .jpg 9 \n
    10 016.jpg 0 .jpg 9 \n
    11 017.jpg 0 .jpg 9 \n
    12 018.jpg 0 .jpg 9 \n
    \n
    size 为该项所在分组的成员个数\n
    依据条件可筛选特别的文件名\n
    '''
    df = pd.DataFrame(filenames, columns=['filenames']) # 即使一维 filenames 也能直接变成竖向
    pattern = r'^(?P<preffix>.+\D)?(?P<number>\d+)(?P<suffix>.+)?'
    # pattern = r'^(?P<preffix>.+?\D)?(?P<number>\d+)(?P<suffix>.+)?'
    df1 = pd.concat([df, df['filenames'].str.extract(pattern, flags=re.IGNORECASE)], axis=1)
    gf = ['preffix','suffix']
    if df1['preffix'].isna().all():
    gf = ['suffix']
    g = df1.groupby(gf, as_index=False)
    df1['size'] = g.transform('size').fillna(0).astype(int)
    return df1.sort_values('size', ascending=False, ignore_index=True)
    ```

    这是一个我经常用的匹配文件名的函数
    你可以用字段名替换 filenames ,然后匹配一下,当然正则和 groupby 部分你要修改一下,改成符合你的需求,这样你就可以把字段名分组了
    NoOneNoBody
        11
    NoOneNoBody  
       9 天前
    Sawyerhou
        12
    Sawyerhou  
       9 天前
    pandas 处理非常容易,可以直接 gpt 一下,如果内存够用,可以试试这个

    df.T.set_index(df.columns.str.findall(r'^([a-z]+)').to_series().explode()).groupby(level=0).sum().T

    如果内存不够用,把上面 groupby 改为手动循环
    NoOneNoBody
        13
    NoOneNoBody  
       9 天前
    cs1024
        14
    cs1024  
    OP
       9 天前
    @NoOneNoBody 谢谢,我尝试一下,
    cs1024
        15
    cs1024  
    OP
       9 天前
    @Sawyerhou 谢谢,
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1202 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 22ms · UTC 18:19 · PVG 02:19 · LAX 11:19 · JFK 14:19
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.