最低值减去组内第二低的值(熊猫,python,groupby)
lowest value subtract second lowest value within a group (panda, python,groupby)
我有一个 df,我可以得到最低单圈时间减法之间的单圈时间差
以及组内的剩余单圈时间
df['diff'] = df['lap_time'] - df.groupby('lap_ref')['lap_time '].transform('min')
原版df
╔═════════╦═════════╦══════════╦══════╗
║ lap_ref ║ swimmer ║ lap_time ║ diff ║
╠═════════╬═════════╬══════════╬══════╣
║ 151 ║ steve ║ 82.64 ║ 0 ║
║ 151 ║ timoy ║ 82.77 ║ 0.13 ║
║ 151 ║ audi ║ 82.83 ║ 0.19 ║
║ 151 ║ gimmi ║ 82.98 ║ 0.34 ║
║ 151 ║ pete ║ 83.08 ║ 0.44 ║
║ 151 ║ manson ║ 83.24 ║ 0.6 ║
║ 151 ║ fuller ║ 83.4 ║ 0.76 ║
║ 151 ║ ron ║ 83.56 ║ 0.92 ║
║ 151 ║ limin ║ 83.62 ║ 0.98 ║
║ 151 ║ octank ║ 83.92 ║ 1.28 ║
║ 151 ║ frank ║ 83.94 ║ 1.3 ║
║ 151 ║ mose ║ 84.15 ║ 1.51 ║
║ 151 ║ preta ║ 84.2 ║ 1.56 ║
║ 151 ║ landra ║ 92.2 ║ 9.56 ║
╚═════════╩═════════╩══════════╩══════╝
我需要用组内最低-第二低的值填充值 0。但是,我找不到解决方案。
尝试获得的结果
╔═════════╦═════════╦══════════╦══════╗
║ lap_ref ║ swimmer ║ lap_time ║ diff ║
╠═════════╬═════════╬══════════╬══════╣
║ 151 ║ steve ║ 82.64 ║-0.13 ║
║ 151 ║ timoy ║ 82.77 ║ 0.13 ║
║ 151 ║ audi ║ 82.83 ║ 0.19 ║
║ 151 ║ gimmi ║ 82.98 ║ 0.34 ║
║ 151 ║ pete ║ 83.08 ║ 0.44 ║
║ 151 ║ manson ║ 83.24 ║ 0.6 ║
║ 151 ║ fuller ║ 83.4 ║ 0.76 ║
║ 151 ║ ron ║ 83.56 ║ 0.92 ║
║ 151 ║ limin ║ 83.62 ║ 0.98 ║
║ 151 ║ octank ║ 83.92 ║ 1.28 ║
║ 151 ║ frank ║ 83.94 ║ 1.3 ║
║ 151 ║ mose ║ 84.15 ║ 1.51 ║
║ 151 ║ preta ║ 84.2 ║ 1.56 ║
║ 151 ║ landra ║ 92.2 ║ 9.56 ║
╚═════════╩═════════╩══════════╩══════╝
data = {'lap_ref':[151,151,151,151,151,151,151,151,151,151,151,151,151,151],
'swimmer':['steve','timoy','audi','gimmi','pete','manson','fuller',
'ron','limin','octank','frank','mose','preta','landra'],
'lap_time':[82.64,82.77,82.83,82.98,83.08,83.24,83.4,83.56,83.62,83.92,83.94,84.15,84.2,92.2]}
请指教。谢谢
我们可以用 pd.Series.nsmallest
然后将值映射回来
s = df.groupby('lap_ref ')['lap_time'].apply(pd.Series.nsmallest,n=2).groupby(level=0).agg(np.ptp).reindex(df['lap_ref ']).values
df['new'] = np.where(df['diff'].eq(0),-s,df['diff'])
df['diff'] = df['lap_time'].diff().cumsum().fillna(-df['lap_time'].diff()[1])
输出:
>>> df
0 -0.13
1 0.13
2 0.19
3 0.34
4 0.44
5 0.60
6 0.76
7 0.92
8 0.98
9 1.28
10 1.30
11 1.51
12 1.56
13 9.56
Name: lap_time, dtype: float64
您可以使用nsmallest
方法。首先使用 .nsmallest
方法找到 2 个最小值,然后使用 .diff
方法找到两者之间的差异。这会产生每个 lap_ref
的第二小和最小之间的差异。由于我们想要第二小和最小之间的差异,所以我们取 max
(因为另一个值是 NaN
)。然后将其转换为字典并使用字典,map
将其转换为 df['lap_ref']
并使用 np.where
,将此值分配给 diff
,其中 df['diff']==0
:
g = df.groupby('lap_ref')['lap_time']
df['diff'] = df['lap_time'] - g.transform('min')
mapper = g.nsmallest(2).diff().droplevel(1).groupby('lap_ref').max().to_dict()
df['diff'] = np.where(df['diff']==0, -df['lap_ref'].map(mapper), df['diff'])
输出:
lap_ref swimmer lap_time diff
0 151 steve 82.64 -0.13
1 151 timoy 82.77 0.13
2 151 audi 82.83 0.19
3 151 gimmi 82.98 0.34
4 151 pete 83.08 0.44
5 151 manson 83.24 0.60
6 151 fuller 83.40 0.76
7 151 ron 83.56 0.92
8 151 limin 83.62 0.98
9 151 octank 83.92 1.28
10 151 frank 83.94 1.30
11 151 mose 84.15 1.51
12 151 preta 84.20 1.56
13 151 landra 92.20 9.56
假设数据已经按降序排序(与当前在共享数据中一样):
grp = df.groupby('lap_ref').lap_time
difference = grp.nth(0) - grp.nth(1)
(df.assign(lap_time = df.lap_time.sub(grp.transform('min')),
diff = lambda df: np.where(df.lap_time.eq(0),
difference.item(),
df.lap_time)
)
)
lap_ref swimmer lap_time diff
0 151 steve 0.00 -0.13
1 151 timoy 0.13 0.13
2 151 audi 0.19 0.19
3 151 gimmi 0.34 0.34
4 151 pete 0.44 0.44
5 151 manson 0.60 0.60
6 151 fuller 0.76 0.76
7 151 ron 0.92 0.92
8 151 limin 0.98 0.98
9 151 octank 1.28 1.28
10 151 frank 1.30 1.30
11 151 mose 1.51 1.51
12 151 preta 1.56 1.56
13 151 landra 9.56 9.56
我有一个 df,我可以得到最低单圈时间减法之间的单圈时间差
以及组内的剩余单圈时间
df['diff'] = df['lap_time'] - df.groupby('lap_ref')['lap_time '].transform('min')
原版df
╔═════════╦═════════╦══════════╦══════╗ ║ lap_ref ║ swimmer ║ lap_time ║ diff ║ ╠═════════╬═════════╬══════════╬══════╣ ║ 151 ║ steve ║ 82.64 ║ 0 ║ ║ 151 ║ timoy ║ 82.77 ║ 0.13 ║ ║ 151 ║ audi ║ 82.83 ║ 0.19 ║ ║ 151 ║ gimmi ║ 82.98 ║ 0.34 ║ ║ 151 ║ pete ║ 83.08 ║ 0.44 ║ ║ 151 ║ manson ║ 83.24 ║ 0.6 ║ ║ 151 ║ fuller ║ 83.4 ║ 0.76 ║ ║ 151 ║ ron ║ 83.56 ║ 0.92 ║ ║ 151 ║ limin ║ 83.62 ║ 0.98 ║ ║ 151 ║ octank ║ 83.92 ║ 1.28 ║ ║ 151 ║ frank ║ 83.94 ║ 1.3 ║ ║ 151 ║ mose ║ 84.15 ║ 1.51 ║ ║ 151 ║ preta ║ 84.2 ║ 1.56 ║ ║ 151 ║ landra ║ 92.2 ║ 9.56 ║ ╚═════════╩═════════╩══════════╩══════╝
我需要用组内最低-第二低的值填充值 0。但是,我找不到解决方案。
尝试获得的结果
╔═════════╦═════════╦══════════╦══════╗ ║ lap_ref ║ swimmer ║ lap_time ║ diff ║ ╠═════════╬═════════╬══════════╬══════╣ ║ 151 ║ steve ║ 82.64 ║-0.13 ║ ║ 151 ║ timoy ║ 82.77 ║ 0.13 ║ ║ 151 ║ audi ║ 82.83 ║ 0.19 ║ ║ 151 ║ gimmi ║ 82.98 ║ 0.34 ║ ║ 151 ║ pete ║ 83.08 ║ 0.44 ║ ║ 151 ║ manson ║ 83.24 ║ 0.6 ║ ║ 151 ║ fuller ║ 83.4 ║ 0.76 ║ ║ 151 ║ ron ║ 83.56 ║ 0.92 ║ ║ 151 ║ limin ║ 83.62 ║ 0.98 ║ ║ 151 ║ octank ║ 83.92 ║ 1.28 ║ ║ 151 ║ frank ║ 83.94 ║ 1.3 ║ ║ 151 ║ mose ║ 84.15 ║ 1.51 ║ ║ 151 ║ preta ║ 84.2 ║ 1.56 ║ ║ 151 ║ landra ║ 92.2 ║ 9.56 ║ ╚═════════╩═════════╩══════════╩══════╝
data = {'lap_ref':[151,151,151,151,151,151,151,151,151,151,151,151,151,151],
'swimmer':['steve','timoy','audi','gimmi','pete','manson','fuller',
'ron','limin','octank','frank','mose','preta','landra'],
'lap_time':[82.64,82.77,82.83,82.98,83.08,83.24,83.4,83.56,83.62,83.92,83.94,84.15,84.2,92.2]}
请指教。谢谢
我们可以用 pd.Series.nsmallest
然后将值映射回来
s = df.groupby('lap_ref ')['lap_time'].apply(pd.Series.nsmallest,n=2).groupby(level=0).agg(np.ptp).reindex(df['lap_ref ']).values
df['new'] = np.where(df['diff'].eq(0),-s,df['diff'])
df['diff'] = df['lap_time'].diff().cumsum().fillna(-df['lap_time'].diff()[1])
输出:
>>> df
0 -0.13
1 0.13
2 0.19
3 0.34
4 0.44
5 0.60
6 0.76
7 0.92
8 0.98
9 1.28
10 1.30
11 1.51
12 1.56
13 9.56
Name: lap_time, dtype: float64
您可以使用nsmallest
方法。首先使用 .nsmallest
方法找到 2 个最小值,然后使用 .diff
方法找到两者之间的差异。这会产生每个 lap_ref
的第二小和最小之间的差异。由于我们想要第二小和最小之间的差异,所以我们取 max
(因为另一个值是 NaN
)。然后将其转换为字典并使用字典,map
将其转换为 df['lap_ref']
并使用 np.where
,将此值分配给 diff
,其中 df['diff']==0
:
g = df.groupby('lap_ref')['lap_time']
df['diff'] = df['lap_time'] - g.transform('min')
mapper = g.nsmallest(2).diff().droplevel(1).groupby('lap_ref').max().to_dict()
df['diff'] = np.where(df['diff']==0, -df['lap_ref'].map(mapper), df['diff'])
输出:
lap_ref swimmer lap_time diff
0 151 steve 82.64 -0.13
1 151 timoy 82.77 0.13
2 151 audi 82.83 0.19
3 151 gimmi 82.98 0.34
4 151 pete 83.08 0.44
5 151 manson 83.24 0.60
6 151 fuller 83.40 0.76
7 151 ron 83.56 0.92
8 151 limin 83.62 0.98
9 151 octank 83.92 1.28
10 151 frank 83.94 1.30
11 151 mose 84.15 1.51
12 151 preta 84.20 1.56
13 151 landra 92.20 9.56
假设数据已经按降序排序(与当前在共享数据中一样):
grp = df.groupby('lap_ref').lap_time
difference = grp.nth(0) - grp.nth(1)
(df.assign(lap_time = df.lap_time.sub(grp.transform('min')),
diff = lambda df: np.where(df.lap_time.eq(0),
difference.item(),
df.lap_time)
)
)
lap_ref swimmer lap_time diff
0 151 steve 0.00 -0.13
1 151 timoy 0.13 0.13
2 151 audi 0.19 0.19
3 151 gimmi 0.34 0.34
4 151 pete 0.44 0.44
5 151 manson 0.60 0.60
6 151 fuller 0.76 0.76
7 151 ron 0.92 0.92
8 151 limin 0.98 0.98
9 151 octank 1.28 1.28
10 151 frank 1.30 1.30
11 151 mose 1.51 1.51
12 151 preta 1.56 1.56
13 151 landra 9.56 9.56