Python 如何基于另一列中的值对单个列的值求和?
我有以下数据帧df:Python 如何基于另一列中的值对单个列的值求和?,python,pandas,sum,Python,Pandas,Sum,我有以下数据帧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
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
我需要对a_1、a_2、a_3的“fea2”值(如1、2、24)求和并保存为a_q1,然后对a_4、a_5、a_6的“fea2”值求和并保存为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,。。。作为一个值,be_1,be_2,be_3,be_4作为。。。一个值。
如何有效地做到这一点?IIUC您需要首先对fea1上的
排序,然后在其上创建组号,这样您就可以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
详情:
- 使用字符串访问器,
.str
和提取
以及用于命名捕获的正则表达式
小组
- 现在,让我们用一点数学来用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
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','r_s1','r_s2','fea2:[1,2,3,7,9,24,5,8,3,7,1,8,1,2]]
#创建数据帧
df=pd.DataFrame(数据)
df['fea1']=df['fea1'].str.replace(“”,“”)
df['Letters','number']=df['fea1'].str.extract('('P[a-zA-Z]+)?('P\d+))
df['grp']=(df['number'].fillna(0).astype(int)-1)//3
df_q=df.groupby(['Letters','grp'])['weight'].sum()
df_q.index=[f'{i}{j+1}'如果j!=-1其他f'{i}'表示df_q.index中的i,j]
df#U q#系列
#将系列转换为数据帧
dff=pd.DataFrame({'fea1':df_q.index,'fea2':df_q.values})
dff
谢谢。但当我有像a_10,a_20这样的值时,就存在一个问题。因为它将fea1排序为a_1,a_10,a_11,…a_19,a_2,a_20,…好的,我如何确定是否需要将3个值或4个值分组在一起?下划线后面的数字是否没有空格。也就是说,在1到20之间的任何顺序中,所有的数字都存在并且只存在一次?我希望它有类似的四分之一。例如,第1节:a_1,a_2,a_3。此外,下划线后面没有空格。是的,这些数字只存在一次。它们只是从1到27的数字。太好了!它起作用了。非常感谢。还有一个问题。那么,如果一些值有如a_s1,a_s2,a_s3,。。。希望只有一点变化。是的,你需要修改普通快车。正则表达式或非正则表达式不太容易学习,但非常实用。您希望字母仅为“a”或“a_s”?这里我只说明了几个值。但我有很多类似的,一些值像a_s1,a_s2,a_s3。这就是为什么要把它作为“a_'s”
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