如何在 For 循环中为多个类别有条件地更新值
Posted
技术标签:
【中文标题】如何在 For 循环中为多个类别有条件地更新值【英文标题】:How to Update Values Conditionally in For Loop for Multiple Categories 【发布时间】:2020-09-15 16:03:15 【问题描述】:我有一个数据框,其中“B”是一个类别,“男孩”是一个事件,对于男孩1,2,3,4,分配了 B = 1;男孩 = 1 使用 B 10 分钟从 12 开始:00 到 End = 12:10 ,下一个男孩应该从 End_Time[0] 开始使用它,就像 B =1 有四个样本和 B = 2 不同的 4 个样本一样
输入样本:
B Boy Start End Out
1 1 12:00 12:10 0:10
1 2 12:01 12:11 0:10
1 3 12:02 12:12 0:10
1 4 12:03 12:13 0:10
2 5 12:00 12:10 0:05
2 6 12:01 12:11 0:05
2 7 12:02 12:12 0:05
2 8 12:03 12:13 0:05
3 9 12:00 12:10 0:03
3 10 12:01 12:11 0:03
3 11 12:02 12:12 0:03
3 12 12:03 12:13 0:03
代码尝试:
data_1['End'] = pd.to_datetime(data_1['Start'] + pd.to_timedelta(data_1['Out'])
for i in range(1, len(data_1)):
data_1.loc[i, 'Start'] = data_1.loc[i-1, 'End']
输出:
B Boy Start End Out
1 1 12:00 12:10 0:10
1 2 12:10 12:20 0:10
1 3 12:20 12:30 0:10
1 4 12:30 12:40 0:10
2 5 12:40 12:45 0:05
2 6 12:45 12:50 0:05
2 7 12:50 12:55 0:05
2 8 12:55 13:00 0:05
3 9 13:00 13:03 0:03
3 10 13:03 13:06 0:03
3 11 13:06 13:09 0:03
3 12 13:09 13:12 0:03
代码失败:
new_Start_time = []
for i,item in data_1.groupby('B'):
temp_list = [item.iloc[0,2]]
list_all = [item.iloc[0,3]]
for j in range(len(list_all)):
temp_list[j+1] = [list_all[j] for i in range(len(list_all) - 1) ]
temp_list.append(temp_list[j])
new_Start_time.extend(temp_list)
data_1['new_Start_time'] = new_Start_time
错误:IndexError:列表分配索引超出范围
预期结果:
B Boy Start End Out
1 1 12:00 12:10 0:10
1 2 12:10 12:20 0:10
1 3 12:20 12:30 0:10
1 4 12:30 12:40 0:10
2 5 12:00 12:05 0:05
2 6 12:05 12:10 0:05
2 7 12:10 12:15 0:05
2 8 12:15 12:20 0:05
3 9 12:00 12:03 0:03
3 10 12:03 12:06 0:03
3 11 12:06 12:09 0:03
3 12 12:09 12:12 0:03
提前致谢
【问题讨论】:
【参考方案1】:我找到了解决方案。如果您的桌子真的很大但它可以工作,这不是最好的。 首先,我将列转换为 datetime 和 timedelta:
df["Start"] = pd.to_datetime(df["Start"], format='%H:%M')
df["End"] = pd.to_datetime(df["End"], format='%H:%M')
df["Out"] = pd.to_timedelta("0"+df["Out"]+":00")
然后是创建新的开始和结束列的代码:
new_start =[]
new_end = []
for i, group in df.groupby("B"):
temp_start =[]
temp_end = []
out = group.iloc[0,4]
for j in range(0,group.shape[0]):
if j==0:
temp_start.append(group.iloc[0,2])
temp_end.append(group.iloc[0,2]+out)
else:
temp_start.append(temp_end[j-1])
temp_end.append(temp_start[j]+out)
new_start.extend(temp_start)
new_end.extend(temp_end)
现在用新值更新旧的开始和结束列:
df["Start"]= new_start
df["End"] = new_end
df
输出:
B Boy Start End Out
0 1 1 1900-01-01 12:00:00 1900-01-01 12:10:00 00:10:00
1 1 2 1900-01-01 12:10:00 1900-01-01 12:20:00 00:10:00
2 1 3 1900-01-01 12:20:00 1900-01-01 12:30:00 00:10:00
3 1 4 1900-01-01 12:30:00 1900-01-01 12:40:00 00:10:00
4 2 5 1900-01-01 12:00:00 1900-01-01 12:05:00 00:05:00
5 2 6 1900-01-01 12:05:00 1900-01-01 12:10:00 00:05:00
6 2 7 1900-01-01 12:10:00 1900-01-01 12:15:00 00:05:00
7 2 8 1900-01-01 12:15:00 1900-01-01 12:20:00 00:05:00
8 3 9 1900-01-01 12:00:00 1900-01-01 12:03:00 00:03:00
9 3 10 1900-01-01 12:03:00 1900-01-01 12:06:00 00:03:00
10 3 11 1900-01-01 12:06:00 1900-01-01 12:09:00 00:03:00
11 3 12 1900-01-01 12:09:00 1900-01-01 12:12:00 00:03:00
【讨论】:
谢谢@DavideBrex,我的 DataFrame 很小,这会很完美。【参考方案2】:你可以使用:
def toTimeDelta(s):
h = pd.to_timedelta(s.str.split(':').str[0].astype(int), unit='h')
m = pd.to_timedelta(s.str.split(':').str[1].astype(int), unit='m')
return h + m
def fx(s):
s = s.transform(toTimeDelta)
out = s['Out'].copy()
out.iloc[0] += s['Start'].iloc[0]
s['End'] = out.cumsum()
s['Start'].iloc[1:] = s['End'].shift().iloc[1:]
return s
df[['Start', 'End', 'Out']] = df.groupby('B')[['Start', 'End', 'Out']].apply(fx)
结果:
# print(df)
B Boy Start End Out
0 1 1 12:00:00 12:10:00 00:10:00
1 1 2 12:10:00 12:20:00 00:10:00
2 1 3 12:20:00 12:30:00 00:10:00
3 1 4 12:30:00 12:40:00 00:10:00
4 2 5 12:00:00 12:05:00 00:05:00
5 2 6 12:05:00 12:10:00 00:05:00
6 2 7 12:10:00 12:15:00 00:05:00
7 2 8 12:15:00 12:20:00 00:05:00
8 3 9 12:00:00 12:03:00 00:03:00
9 3 10 12:03:00 12:06:00 00:03:00
10 3 11 12:06:00 12:09:00 00:03:00
11 3 12 12:09:00 12:12:00 00:03:00
【讨论】:
以上是关于如何在 For 循环中为多个类别有条件地更新值的主要内容,如果未能解决你的问题,请参考以下文章
如何使用for循环或条件在pandas数据框的子集中创建多个回归模型(statsmodel)?