“姓名”列在一行中包含一个人的姓名,然后是他们需要执行的编号任务(带有简短描述),所有任务都与该人的姓名相关联,直到出现另一个人的姓名(所以汤姆拥有所有他名字下面的任务与 Tom 关联,直到 Jim 出现,然后 Jim 与他名字后面的所有任务关联,直到下一个名字......等等)。所以这是我拥有的数据示例:
Name Three Digit Task Number of Days
Tom BLANK 0.00
1.1.6.1 Task Description 1.1.6 9.00
1.1.6.2 Task Description 1.1.6 8.25
1.1.1.4 Task Description 1.1.1 13.25
Jim BLANK 0.00
1.1.3.1 Task Description 1.1.3 8.75
1.2.1.1 Task Description 1.2.1 6.00
1.2.1.2 Task Description 1.2.1 12.75
所以我想得到每个人的天数总和,按三位数任务分组。希望它看起来像这样:
Tom 1.1.1 13.25
Tom 1.1.6 17.25
Jim 1.1.3 8.75
Jim 1.2.1 18.75
所以我尝试使用:
import string
ALPHA = string.ascii_letters
df['Name'].str.startswith(tuple(ALPHA))
如果“名称”列是否以字母开头,则返回真/假(字母为真,否则为假)。试图说类似的话:在真实(这将是人们的名字)之间通过对“三位数任务”进行分组来总结“天数”
最佳答案
tl;博士
name_bool = df.Name.str.match('^[a-zA-Z]')
grp_keys = name_bool.cumsum()
grps = df.groupby(grp_keys)
tdt = 'Three Digit Task'
nod = 'Number of Days'
funcs = {'Name': 'first', nod: 'sum'}
dicts = {g.iloc[0, 0]: g.tail(-1).groupby(tdt).agg(funcs) for _, g in grps}
pd.concat(dicts)
解释
使用 regex
查找哪些行具有以字母开头的 Name
列。
name_bool = df.Name.str.match('^[a-zA-Z]')
name_bool
0 True
1 False
2 False
3 False
4 True
5 False
6 False
7 False
Name: Name, dtype: bool
使用 cumsum
为 Name
之后的每组连续行创建一个唯一编号
grp_keys = name_bool.cumsum()
grp_keys
0 1
1 1
2 1
3 1
4 2
5 2
6 2
7 2
Name: Name, dtype: int64
创建 pandas groupby
对象
grps = df.groupby(grp_keys)
使用agg
和pd.concat
创建最终的pd.DataFrame
funcs = {'Name': 'first', nod: 'sum'}
dicts = {g.iloc[0, 0]: g.tail(-1).groupby(tdt).agg(funcs) for _, g in grps}
pd.concat(dicts)
关于python - 根据条件Python对多行进行分组/求和,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41105991/