使用 Pandas 为每个过滤器识别列中最接近的值
Identifying closest value in a column for each filter using Pandas
我有一个包含类别和值的数据框。我需要在每个类别中找到最接近某个值的值。我想我已经接近了,但是在将 argsort 的结果应用于原始数据帧时我无法真正获得正确的输出。
例如,如果在下面的代码中定义了输入,则输出应该只有 (a, 1, True)
、(b, 2, True)
、(c, 2, True)
,所有其他 isClosest Values
应该是错误。
如果多个值最接近,那么它应该是列出的第一个标记的值。
这是我拥有的有效代码,但我无法将其正确地重新应用于数据框。我希望得到一些指点。
df = pd.DataFrame()
df['category'] = ['a', 'b', 'b', 'b', 'c', 'a', 'b', 'c', 'c', 'a']
df['values'] = [1, 2, 3, 4, 5, 4, 3, 2, 1, 0]
df['isClosest'] = False
uniqueCategories = df['category'].unique()
for c in uniqueCategories:
filteredCategories = df[df['category']==c]
sortargs = (filteredCategories['value']-2.0).abs().argsort()
#how to use sortargs so that we set column in df isClosest=True if its the closest value in each category to 2.0?
您可以创建一个绝对差异列:
df['dif'] = (df['values'] - 2).abs()
df
Out:
category values dif
0 a 1 1
1 b 2 0
2 b 3 1
3 b 4 2
4 c 5 3
5 a 4 2
6 b 3 1
7 c 2 0
8 c 1 1
9 a 0 2
然后用groupby.transform
检查每组的最小值是否等于你计算的差:
df['is_closest'] = df.groupby('category')['dif'].transform('min') == df['dif']
df
Out:
category values dif is_closest
0 a 1 1 True
1 b 2 0 True
2 b 3 1 False
3 b 4 2 False
4 c 5 3 False
5 a 4 2 False
6 b 3 1 False
7 c 2 0 True
8 c 1 1 False
9 a 0 2 False
df.groupby('category')['dif'].idxmin()
还会为您提供每个类别的最接近值的索引。您也可以将其用于映射。
供选择:
df.loc[df.groupby('category')['dif'].idxmin()]
Out:
category values dif
0 a 1 1
1 b 2 0
7 c 2 0
作业:
df['is_closest'] = False
df.loc[df.groupby('category')['dif'].idxmin(), 'is_closest'] = True
df
Out:
category values dif is_closest
0 a 1 1 True
1 b 2 0 True
2 b 3 1 False
3 b 4 2 False
4 c 5 3 False
5 a 4 2 False
6 b 3 1 False
7 c 2 0 True
8 c 1 1 False
9 a 0 2 False
这些方法之间的区别在于,如果您根据差异检查相等性,那么在出现平局的情况下,所有行都会得到 True。但是,对于 idxmin
,第一次出现时它将 return 为真(每个组只有一个)。
DataFrameGroupBy.idxmin
- get indexes of minimal values per group and then assign boolean mask by Index.isin
列 isClosest
的解决方案:
idx = (df['values'] - 2).abs().groupby([df['category']]).idxmin()
print (idx)
category
a 0
b 1
c 7
Name: values, dtype: int64
df['isClosest'] = df.index.isin(idx)
print (df)
category values isClosest
0 a 1 True
1 b 2 True
2 b 3 False
3 b 4 False
4 c 5 False
5 a 4 False
6 b 3 False
7 c 2 True
8 c 1 False
9 a 0 False
我有一个包含类别和值的数据框。我需要在每个类别中找到最接近某个值的值。我想我已经接近了,但是在将 argsort 的结果应用于原始数据帧时我无法真正获得正确的输出。
例如,如果在下面的代码中定义了输入,则输出应该只有 (a, 1, True)
、(b, 2, True)
、(c, 2, True)
,所有其他 isClosest Values
应该是错误。
如果多个值最接近,那么它应该是列出的第一个标记的值。
这是我拥有的有效代码,但我无法将其正确地重新应用于数据框。我希望得到一些指点。
df = pd.DataFrame()
df['category'] = ['a', 'b', 'b', 'b', 'c', 'a', 'b', 'c', 'c', 'a']
df['values'] = [1, 2, 3, 4, 5, 4, 3, 2, 1, 0]
df['isClosest'] = False
uniqueCategories = df['category'].unique()
for c in uniqueCategories:
filteredCategories = df[df['category']==c]
sortargs = (filteredCategories['value']-2.0).abs().argsort()
#how to use sortargs so that we set column in df isClosest=True if its the closest value in each category to 2.0?
您可以创建一个绝对差异列:
df['dif'] = (df['values'] - 2).abs()
df
Out:
category values dif
0 a 1 1
1 b 2 0
2 b 3 1
3 b 4 2
4 c 5 3
5 a 4 2
6 b 3 1
7 c 2 0
8 c 1 1
9 a 0 2
然后用groupby.transform
检查每组的最小值是否等于你计算的差:
df['is_closest'] = df.groupby('category')['dif'].transform('min') == df['dif']
df
Out:
category values dif is_closest
0 a 1 1 True
1 b 2 0 True
2 b 3 1 False
3 b 4 2 False
4 c 5 3 False
5 a 4 2 False
6 b 3 1 False
7 c 2 0 True
8 c 1 1 False
9 a 0 2 False
df.groupby('category')['dif'].idxmin()
还会为您提供每个类别的最接近值的索引。您也可以将其用于映射。
供选择:
df.loc[df.groupby('category')['dif'].idxmin()]
Out:
category values dif
0 a 1 1
1 b 2 0
7 c 2 0
作业:
df['is_closest'] = False
df.loc[df.groupby('category')['dif'].idxmin(), 'is_closest'] = True
df
Out:
category values dif is_closest
0 a 1 1 True
1 b 2 0 True
2 b 3 1 False
3 b 4 2 False
4 c 5 3 False
5 a 4 2 False
6 b 3 1 False
7 c 2 0 True
8 c 1 1 False
9 a 0 2 False
这些方法之间的区别在于,如果您根据差异检查相等性,那么在出现平局的情况下,所有行都会得到 True。但是,对于 idxmin
,第一次出现时它将 return 为真(每个组只有一个)。
DataFrameGroupBy.idxmin
- get indexes of minimal values per group and then assign boolean mask by Index.isin
列 isClosest
的解决方案:
idx = (df['values'] - 2).abs().groupby([df['category']]).idxmin()
print (idx)
category
a 0
b 1
c 7
Name: values, dtype: int64
df['isClosest'] = df.index.isin(idx)
print (df)
category values isClosest
0 a 1 True
1 b 2 True
2 b 3 False
3 b 4 False
4 c 5 False
5 a 4 False
6 b 3 False
7 c 2 True
8 c 1 False
9 a 0 False