我见过:
这些与香草蟒蛇有关,而不是熊猫。
如果我有这个系列:
ix num
0 1
1 6
2 4
3 5
4 2
我输入3,我怎样才能(有效地)找到?
IE中。使用上面的系列{1,6,4,5,2}和输入3,我应该得到带有索引(2,4)的值(4,2)。
答案 0 :(得分:30)
您可以使用argsort()
之类的
说,input = 3
In [198]: input = 3
In [199]: df.ix[(df['num']-input).abs().argsort()[:2]]
Out[199]:
num
2 4
4 2
df_sort
是具有2个最接近值的数据框。
In [200]: df_sort = df.ix[(df['num']-input).abs().argsort()[:2]]
索引,
In [201]: df_sort.index.tolist()
Out[201]: [2, 4]
对于值,
In [202]: df_sort['num'].tolist()
Out[202]: [4, 2]
详细信息,对于上述解决方案df
是
In [197]: df
Out[197]:
num
0 1
1 6
2 4
3 5
4 2
答案 1 :(得分:15)
除了John Galt的回答之外,我建议使用iloc
,因为即使使用未排序的整数索引,这也会有效,因为.ix首先查看索引标签
df.iloc[(df['num']-input).abs().argsort()[:2]]
答案 2 :(得分:3)
这里讨论的其他算法的一个缺点是它们必须对整个列表进行排序。这导致〜N log(N)的复杂性。
但是,可以在〜N 中获得相同的结果。这种方法将数据帧分为两个子集,一个子集小于期望值。在较小的数据框中,较低的邻居比最大值大,而对于较高的邻居,反之亦然。
这给出了以下代码片段:
def find_neighbours(value):
exactmatch=df[df.num==value]
if !exactmatch.empty:
return exactmatch.index[0]
else:
lowerneighbour_ind = df[df.num<value].idxmax()
upperneighbour_ind = df[df.num>traversed].idxmin()
return lowerneighbour_ind, upperneighbour_ind
此方法类似于使用partition in pandas,当处理大型数据集且复杂性成为问题时,它确实非常有用。
答案 3 :(得分:2)
如果您的系列已经排序,您可以使用类似的东西。
def closest(df, col, val, direction):
n = len(df[df[col] <= val])
if(direction < 0):
n -= 1
if(n < 0 or n >= len(df)):
print('err - value outside range')
return None
return df.ix[n, col]
df = pd.DataFrame(pd.Series(range(0,10,2)), columns=['num'])
for find in range(-1, 2):
lc = closest(df, 'num', find, -1)
hc = closest(df, 'num', find, 1)
print('Closest to {} is {}, lower and {}, higher.'.format(find, lc, hc))
df: num
0 0
1 2
2 4
3 6
4 8
err - value outside range
Closest to -1 is None, lower and 0, higher.
Closest to 0 is 0, lower and 2, higher.
Closest to 1 is 0, lower and 2, higher.
答案 4 :(得分:1)
如果系列已经排序,则使用bisect是查找索引的有效方法。 一个例子:
idx = bisect_right(df['num'].values, 3)
因此对于问题中提到的问题,考虑对数据帧“ df”的列“ col”进行排序:
from bisect import bisect_right, bisect_left
def get_closests(df, col, val):
lower_idx = bisect_right(df[col].values, val)
higher_idx = bisect_left(df[col].values, val)
if higher_idx == lower_idx:
return lower_idx
else:
return lower_idx, higher_idx
在数据框列“ col”或其最接近的邻居中找到特定值“ val”的索引是非常有效的,但是它要求对列表进行排序。
答案 5 :(得分:0)
您可以使用numpy.searchsorted
。如果您的搜索列尚未排序,则可以创建一个已排序的DataFrame并使用pandas.argsort
记住它们之间的映射。 (如果您计划多次查找最接近的值,则比上述方法要好。)
对它进行排序后,就可以像这样找到最接近的输入值:
indLeft = np.searchsorted(df['column'], input, side='left')
indRight = np.searchsorted(df['column'], input, side='right')
valLeft = df['column'][indLeft]
valRight = df['column'][indRight]
答案 6 :(得分:0)
这里有很多答案,其中很多都很好。没有人接受,并且@Zero的答案是目前最高的评价。另一个答案指出,当尚未对索引进行排序时,它不起作用,但是他/她建议使用一种似乎已过时的解决方案。
我发现我可以按以下方式在值本身上使用argsort()
的numpy版本,即使索引未排序也可以使用:
df.iloc[(df['num']-input).abs()..values.argsort()[:2]]
有关上下文,请参见Zero的答案。
答案 7 :(得分:0)
我发现解决此类问题的最直观方法是使用@ivo-merchiers 建议的分区方法,但使用 nsmallest 和 nlargest。除了处理未排序的系列之外,这种方法的一个好处是您可以通过将 k_matches 设置为大于 1 的数字轻松获得多个接近值。
import pandas as pd
source = pd.Series([1,6,4,5,2])
target = 3
def find_closest_values(target, source, k_matches=1):
k_above = source[source >= target].nsmallest(k_matches)
k_below = source[source < target].nlargest(k_matches)
k_all = pd.concat([k_below, k_above]).sort_values()
return k_all
find_closest_values(target, source, k_matches=1)
输出:
4 2
2 4
dtype: int64