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

11 天前
 cs1024
原始表
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(老字段名的内容)


不知道有没有简单的方法解决这个问题,
感谢感谢~
666 次点击
所在节点    程序员
15 条回复
NoOneNoBody
11 天前
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
11 天前
嗯,sql select 漏了 id ,自行补上
cs1024
11 天前
@NoOneNoBody

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

直接硬编码太复杂了,
lbaob
11 天前
python 里面,用 sql 语句获取表字段信息,然后根据字段生成 sql
NoOneNoBody
11 天前
哦,漏看了,这样 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
11 天前
#5 typo ,应是 columns
NoOneNoBody
11 天前
再补充一下,用正则的话
str.contains 是部分匹配,用 str.match 是整个字段名匹配,可以选择不同的方式和对应的正则
也可以不用正则,参数改为 regex=False 即可
cs1024
11 天前
@NoOneNoBody

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

你这个字段名有什么规律么,是否必然是字母或多个字母+数字,字符和数字两个是否分开
然后,相同的字母组合,其数字是否必定是正整数,例如 1,2,3,4……顺序可以不对,但是否有缺的,如 1,2,4……
只要有规律,自然可用正则来捕获
pattern = r'^(?P<preffix>.+\D)?(?P<number>\d+)(?P<suffix>.+)?'
类似这样的正则就能分开了,然后用 groupby 就能找到符合的一批字段名
NoOneNoBody
11 天前
```
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 天前
Sawyerhou
11 天前
pandas 处理非常容易,可以直接 gpt 一下,如果内存够用,可以试试这个

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

如果内存不够用,把上面 groupby 改为手动循环
NoOneNoBody
11 天前
cs1024
11 天前
@NoOneNoBody 谢谢,我尝试一下,
cs1024
11 天前
@Sawyerhou 谢谢,

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1050302

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX