我有一个熊猫数据框,看起来像:
a
0 0
1 -2
2 4
3 1
4 6
我也有一个列表
A = [-1, 2, 5, 7]
我想添加一个名为“ b”的新列,该列包含A中的最大值,该值小于列“ a”中的单元格值。如果不存在这样的值,则我希望“ b”中的值为“ X”。因此,目标是获得:
a b
0 0 -1
1 -2 X
2 4 2
3 1 -1
4 6 5
我该如何实现?
答案 0 :(得分:5)
有一个内置函数merge_asof
s=pd.DataFrame({'a':A,'b':A})
pd.merge_asof(df.assign(index=df.index).sort_values('a'),s,on='a').set_index('index').sort_index().fillna('X')
Out[284]:
a b
index
0 0 -1
1 -2 X
2 4 2
3 1 -1
4 6 5
答案 1 :(得分:2)
def largest_min(x):
less_than = list(filter(lambda l: l < x, A))
if len(less_than):
return max(less_than)
return 'X'
df['b'] = df['a'].apply(largest_min)
已修改:要修复错误,如果没有找到值,则修复'X'
答案 2 :(得分:2)
不确定是否使用pandas
方法,但是numpy.searchsorted
在这里很合适。
找到应在其中插入元素以保持顺序的索引。
一旦有了插入元素以保持排序的索引,就可以在查找数组中查看这些索引的 left 左边的元素,以找到最接近的较小元素。如果将元素插入列表的开头(索引0),我们知道查找列表中不存在较小的元素,因此我们使用np.where
A = np.array([-1, 2, 5, 7])
r = np.searchsorted(A, df.a.values)
df.assign(b=np.where(r == 0, np.nan, A[r-1])).fillna('X')
a b
0 0 -1
1 -2 X
2 4 2
3 1 -1
4 6 5
此方法比此处的apply
快得多。
df = pd.concat([df]*10_000)
%%timeit
r = np.searchsorted(A, df.a.values)
df.assign(b=np.where(r == 0, np.nan, A[r-1])).fillna('X')
6.09 ms ± 367 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit df['a'].apply(largest_min)
196 ms ± 5.1 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
答案 3 :(得分:0)
这也是另一种方法:
df1 = pd.Series(A)
def filler(val):
v = df1[df1 < val.iloc[0]].max()
return v
df.assign(b=df.apply(filler, axis=1).fillna('X'))
a b
0 0 -1
1 -2 X
2 4 2
3 1 -1
4 6 5
答案 4 :(得分:-1)
df = pd.DataFrame({'a':[0,1,4,1,6]})
A = [-1,2,5,7]
new_list = []
for i in df.iterrows():
for j in range(len(A)):
if A[j] < i[1]['a']:
print(A[j])
pass
elif j == 0:
new_list.append(A[j])
break
else:
new_list.append(A[j-1])
break
df['b'] = new_list