我想创建2个新列,这些列将为我提供最接近某个值的值和ID。这就是我在python中的df的结构:
x_time expiration x_price p_time p_price
100 4 55.321 100 21
105 4 51.120 105 25
110 4 44.412 110 33.1
100 5 9.1 100 3.1
105 5 9.5 105 5.1
110 5 8.2 110 12.1
100 6 122.1 100 155.9
105 6 144.1 105 134.2
.......
本质上,我想创建一个新列(称为“ closest_time”和“ closest_price”),该列将仅是该组与x_price最为接近的p_price(因此该组将按过期时间显示)
因此,预期结果将如下所示:
x_time expiration x_price p_time p_price closest_price closest_p_time
100 4 55.321 100 21 33.1 110
105 4 51.120 105 25 33.1 110
110 4 44.412 110 33.1 33.1 110
100 5 9.1 100 3.1 12.1 110
105 5 9.5 105 5.1 12.1 110
110 5 8.2 110 12.1 5.1 105
100 6 122.1 100 155.9 134.2 105
105 6 144.1 105 134.2 134.22 100
希望这有点道理。
我已经想到了执行此操作的潜在方法:
但是,我没有成功。
谢谢!
答案 0 :(得分:3)
我认为这是一个不错的解决方案:
df['closest_price'] = \
df.apply(lambda x: df[df.p_price <= x.x_price]['p_price'].max(), axis=1)
答案 1 :(得分:2)
我不确定您的预期结果是否正确-最后一行似乎错了,144.1比155.9更接近134.2,因此,最近的_p_time应该为105?
我这样做的方法是先查找包含最接近值的行,然后为这些行选择价格和时间。
import io
d = """
x_time expiration x_price p_time p_price
100 4 55.321 100 21
105 4 51.120 105 25
110 4 44.412 110 33.1
100 5 9.1 100 3.1
105 5 9.5 105 5.1
110 5 8.2 110 12.1
100 6 122.1 100 155.9
105 6 144.1 105 134.2
"""
df = pd.read_csv(io.StringIO(d), delim_whitespace=True)
idx_lookup = df.apply(lambda x: (df.loc[df['expiration'] == x['expiration'], 'p_price'] - x['x_price']).abs().idxmin(), axis=1)
df['closest_p_price'] = df.loc[idx_lookup, 'p_price'].values
df['closest_p_time'] = df.loc[idx_lookup, 'p_time'].values
哪个给出了数据框
x_time expiration x_price p_time p_price closest_p_price closest_p_time
0 100 4 55.321 100 21.0 33.1 110
1 105 4 51.120 105 25.0 33.1 110
2 110 4 44.412 110 33.1 33.1 110
3 100 5 9.100 100 3.1 12.1 110
4 105 5 9.500 105 5.1 12.1 110
5 110 5 8.200 110 12.1 5.1 105
6 100 6 122.100 100 155.9 134.2 105
7 105 6 144.100 105 134.2 134.2 105
请注意,此用法沿axis=1
沿用,实际上贯穿每一行。我还没有想到更好的方法。
答案 2 :(得分:1)
好的,我的尝试。我使用的是自定义函数,该函数是从this帖子中获取的,该函数将一列转换为基于值的数组。然后,我使用groupby和transform运行您想要的数组以找到最接近的匹配项。
def find_nearest(array, values):
array = np.asarray(array)
# the last dim must be 1 to broadcast in (array - values) below.
values = np.expand_dims(values, axis=-1)
indices = np.abs(array - values).argmin(axis=-1)
return array[indices]
## lets use a lambda with transform to assign this back to our main df
df['closest_price'] = df.groupby('expiration')['x_price'].transform(lambda x : find_nearest(df['p_price'],x))
df['closest_time'] = df.groupby('expiration')['x_time'].transform(lambda x : find_nearest(df['p_time'],x))
print(df)
x_time expiration x_price p_time p_price closest_price closest_time
0 100 4 55.321 100 21.0 33.1 100
1 105 4 51.120 105 25.0 33.1 105
2 110 4 44.412 110 33.1 33.1 110
3 100 5 9.100 100 3.1 12.1 100
4 105 5 9.500 105 5.1 12.1 105
5 110 5 8.200 110 12.1 5.1 110
6 100 6 122.100 100 155.9 134.2 100
7 105 6 144.100 105 134.2 134.2 105