我有以下Panda DataFrame df:
fea1 fea2
0 a_1 1
1 a_2 2
2 a_4 3
3 a_8 7
4 u 9
5 be_1 5
6 a_3 24
7 a_5 5
8 a_6 8
9 be_4 6
9 a_10 9
10 be_3 1
11 be_2 4
12 be_5 3
13 be_6 2
我需要总结一下";fea2";a_1、a_2、a_3的值(如1,2,24(并保存为a_q1,然后求和";fea2";a_4、a_5、a_6的值,并另存为a_q2。此外,对于be_1、be_2和be_3等也是如此。类似下面的
fea1 fea2
0 a_q1 27
1 a_q2 16
2 a_8 7
3 be_q1 10
4 be_q2 11
5 u 9
我试过这个
df.groupby(df['fea1'].str.extract(r'^(D+)', expand=False))['fea2'].sum().reset_index()
但它把所有的a_1,a_2,a_3,a_4,。。。作为一个值,be1,be2,be3,be4作为…一个值。如何有效地做到这一点?
IIUC您需要首先在fea1
上创建sort
,然后在其上创建组号,以便可以groupby
:
df = df.sort_values("fea1")
df["group"] = df.groupby(df["fea1"].str[0]).cumcount()//3
print (df.groupby([df["fea1"].str[0], "group"])["fea2"].sum())
fea1 group
a 0 27
1 16
2 7
u 0 9
让我们试试这个:
df[['Letters', 'number']] = df['fea1'].str.extract('(?P<letters>[a-zA-Z]+)_?(?P<number>d+)?')
df['grp'] = (df['number'].fillna(0).astype(int) - 1) // 3
df_q = df.groupby(['Letters', 'grp'])['fea2'].sum()
df_q.index = [f'{i}_q{j+1}' if j != -1 else f'{i}' for i, j in df_q.index]
df_q
输出:
a_q1 27
a_q2 16
a_q3 7
a_q4 9
be_q1 10
be_q2 9
u 9
Name: fea2, dtype: int64
详细信息:
- 使用字符串访问器
.str
、extract
和正则表达式进行命名捕获小组 - 现在,让我们用一点数学来用除数3对行进行分组
- 接下来,使用
groupby
和sum
- 最后,使用列表理解和f字符串格式
感谢您的帮助@Scott Boston。我改变了一点,效果很好。所以,我在这里发布了完整的代码和你的代码。
data = {'fea1':['a_1', 'a_2', 'a_4', 'a_8', 'u', 'a_3', 'a_5', 'a_6', 'a_10', 'a_20','be_1','be_2','be_3','r_s1','r_s2'], 'fea2':[1, 2,3,7,9,24,5,8,3,7,1,8,4,1,2]}
# Create DataFrame
df = pd.DataFrame(data)
df['fea1'] = df['fea1'].str.replace('_', '')
df[['Letters', 'number']] = df['fea1'].str.extract('(?P<letters>[a-zA-Z]+)?(?P<number>d+)?')
df['grp'] = (df['number'].fillna(0).astype(int) - 1) // 3
df_q = df.groupby(['Letters', 'grp'])['weight'].sum()
df_q.index = [f'{i}_q{j+1}' if j != -1 else f'{i}' for i, j in df_q.index]
df_q #series
# converting series as dataframe
dff = pd.DataFrame({'fea1':df_q.index, 'fea2':df_q.values})
dff