Python 查找多个值的最近索引
我正在尝试查找列中多个值的最近索引范围。我添加了一个python的最小工作代码,如下所示。我的数据范围比这个示例中的要大。它有3000多行。下面的操作和我预期的一样,但处理时间稍长,大约50-60秒 我怎样才能减少这段时间?这种情况有不同的处理方法吗 不是:我的X型和Y型VAL在“列表”和“VAL”列中,Python 查找多个值的最近索引,python,Python,我正在尝试查找列中多个值的最近索引范围。我添加了一个python的最小工作代码,如下所示。我的数据范围比这个示例中的要大。它有3000多行。下面的操作和我预期的一样,但处理时间稍长,大约50-60秒 我怎样才能减少这段时间?这种情况有不同的处理方法吗 不是:我的X型和Y型VAL在“列表”和“VAL”列中, 正面X VAL位于“观察”列中 尝试使用FindNearest函数获取索引编号和计算的Y VAL import numpy as np import pandas as pd from dat
正面X VAL位于“观察”列中
尝试使用FindNearest函数获取索引编号和计算的Y VAL
import numpy as np
import pandas as pd
from datetime import datetime as dt
def FindNearest(Table, Value):
idx = Table['list'].sub(Value).abs().idxmin() # find nearest index no
row_nrst = Table.loc[idx] # get all vals at nearest
# is value big (-1) or small (+1) from nearest, to decide second nearest val
updwn = -1 if Value > row_nrst['list'] else 1
# get model vals that value is between of them
lst1, lval1 = row_nrst[['list', 'vals']]
lst2, lval2 = Table.loc[idx+updwn, ['list', 'vals']]
#calculate observed Y val
rvals = lval1 + (lval2-lval1)*(Value-lst1)/(lst2-lst1)
return pd.Series([idx, rvals])
start = dt.now()
aa = np.matrix([
[ 15, 14, 13, 12, 11, 10, 9, 8], # model X vals
[ 100.5, 94.5, 88.5, 66.5, 74.5, 91.5, 105.5, 120.5], # model Y vals
[12.3, 14.6, 8.7, 13.5, 14.2, 9.4, 11.3, 11.5], # observed X vals
[-1, -1, -1, -1, -1, -1, -1, -1], # index of model X vals
[-1, -1, -1, -1, -1, -1, -1, -1] # calculalted observed Y vals
]).transpose()
tbl = pd.DataFrame(aa, columns=['list', 'vals', 'obser', 'ids', 'obsval'])
# finding process is peformed with **apply** function of Pandas library
tbl[['ids', 'obsval']] = tbl.apply(lambda x: FindNearest(tbl, x['obser']), axis=1)
elapsed = dt.now() - start
print(tbl)
print('Elapsed time :%2.3Fsn'%(elapsed.total_seconds()))
这里有一个方法,它对数据进行一次遍历,以创建具有最接近索引的列 这是您的原始代码
import pandas as pd
import numpy as np
aa = np.matrix([
[ 15, 14, 13, 12, 11, 10, 9, 8], # model X vals
[ 100.5, 94.5, 88.5, 66.5, 74.5, 91.5, 105.5, 120.5], # model Y vals
[12.3, 14.6, 8.7, 13.5, 14.2, 9.4, 11.3, 11.5], # observed X vals
[-1, -1, -1, -1, -1, -1, -1, -1], # index of model X vals
[-1, -1, -1, -1, -1, -1, -1, -1] # calculated observed Y vals
]).transpose()
tbl = pd.DataFrame(aa, columns=['list', 'vals', 'obser', 'ids', 'obsval'])
然后我添加了两个哨兵行作为第一行和最后一行
bb = np.matrix([
[ -999, 999], # model X vals
[ 0.0, 0.0], # model Y vals
[float ("-inf"), float("inf")], # observed X vals
[-1, -1], # index of model X vals
[-1, -1] # calculated observed Y vals
]).transpose()
sentinel = pd.DataFrame(bb, columns=['list', 'vals', 'obser', 'ids', 'obsval'])
sentinel.head()
然后我创建了一个单独的数据框,它将您的数据与sentinel行组合在一起,进行排序
df = tbl.append(sentinel, ignore_index=False)
df.sort_values('obser', inplace=True)
print (df.head(10))
结果如下:
list vals obser ids obsval
0 -999.0 0.0 -inf -1.0 -1.0
2 13.0 88.5 8.7 -1.0 -1.0
5 10.0 91.5 9.4 -1.0 -1.0
6 9.0 105.5 11.3 -1.0 -1.0
7 8.0 120.5 11.5 -1.0 -1.0
0 15.0 100.5 12.3 -1.0 -1.0
3 12.0 66.5 13.5 -1.0 -1.0
4 11.0 74.5 14.2 -1.0 -1.0
1 14.0 94.5 14.6 -1.0 -1.0
1 999.0 0.0 inf -1.0 -1.0
最后,创建三行:prev、curr和next。比较观察者并从两者中选择较小者
closest_idx = []
for i, row in enumerate(df[:2].itertuples()):
if i == 0:
print ('setting prev')
prev = row
if i == 1:
print ('setting curr')
curr = row
for i, next in enumerate(df[2:].itertuples()):
if (next.obser - curr.obser) > (curr.obser - prev.obser):
closer_idx = prev.Index
else:
closer_idx = next.Index
print (f'for row {i}, using {closer_idx}')
prev = curr
curr = next
closest_idx.append(closer_idx)
print (f'{closest_idx}')
这将打印出最近的索引行:
[5, 2, 7, 6, 7, 4, 1, 4]
这里有一个方法,它对数据进行一次遍历,以创建具有最接近索引的列 这是您的原始代码
import pandas as pd
import numpy as np
aa = np.matrix([
[ 15, 14, 13, 12, 11, 10, 9, 8], # model X vals
[ 100.5, 94.5, 88.5, 66.5, 74.5, 91.5, 105.5, 120.5], # model Y vals
[12.3, 14.6, 8.7, 13.5, 14.2, 9.4, 11.3, 11.5], # observed X vals
[-1, -1, -1, -1, -1, -1, -1, -1], # index of model X vals
[-1, -1, -1, -1, -1, -1, -1, -1] # calculated observed Y vals
]).transpose()
tbl = pd.DataFrame(aa, columns=['list', 'vals', 'obser', 'ids', 'obsval'])
然后我添加了两个哨兵行作为第一行和最后一行
bb = np.matrix([
[ -999, 999], # model X vals
[ 0.0, 0.0], # model Y vals
[float ("-inf"), float("inf")], # observed X vals
[-1, -1], # index of model X vals
[-1, -1] # calculated observed Y vals
]).transpose()
sentinel = pd.DataFrame(bb, columns=['list', 'vals', 'obser', 'ids', 'obsval'])
sentinel.head()
然后我创建了一个单独的数据框,它将您的数据与sentinel行组合在一起,进行排序
df = tbl.append(sentinel, ignore_index=False)
df.sort_values('obser', inplace=True)
print (df.head(10))
结果如下:
list vals obser ids obsval
0 -999.0 0.0 -inf -1.0 -1.0
2 13.0 88.5 8.7 -1.0 -1.0
5 10.0 91.5 9.4 -1.0 -1.0
6 9.0 105.5 11.3 -1.0 -1.0
7 8.0 120.5 11.5 -1.0 -1.0
0 15.0 100.5 12.3 -1.0 -1.0
3 12.0 66.5 13.5 -1.0 -1.0
4 11.0 74.5 14.2 -1.0 -1.0
1 14.0 94.5 14.6 -1.0 -1.0
1 999.0 0.0 inf -1.0 -1.0
最后,创建三行:prev、curr和next。比较观察者并从两者中选择较小者
closest_idx = []
for i, row in enumerate(df[:2].itertuples()):
if i == 0:
print ('setting prev')
prev = row
if i == 1:
print ('setting curr')
curr = row
for i, next in enumerate(df[2:].itertuples()):
if (next.obser - curr.obser) > (curr.obser - prev.obser):
closer_idx = prev.Index
else:
closer_idx = next.Index
print (f'for row {i}, using {closer_idx}')
prev = curr
curr = next
closest_idx.append(closer_idx)
print (f'{closest_idx}')
这将打印出最近的索引行:
[5, 2, 7, 6, 7, 4, 1, 4]
我想你是在寻找最近的观察者。不必多次搜索整个列表,也许您可以创建一个新的临时列,即每列的绝对值减去该值?然后根据abs值进行升序排序并返回最小值。我试图为观测到的X VAL的每个元素找到最接近的X VAL模型值。在这种情况下,不适合使用单个temproray列进行最近的搜索。为什么不适合?这似乎是您要求的“更好的方法”。我们应该如何创建此专栏?可以举个例子吗?我想你在寻找最接近的观察者。不必多次搜索整个列表,也许您可以创建一个新的临时列,即每列的绝对值减去该值?然后根据abs值进行升序排序并返回最小值。我试图为观测到的X VAL的每个元素找到最接近的X VAL模型值。在这种情况下,不适合使用单个temproray列进行最近的搜索。为什么不适合?这似乎是您要求的“更好的方法”。我们应该如何创建此专栏?可以举个例子吗?