根据排名第二的熊猫创建新列

时间:2020-06-22 20:19:22

标签: python pandas

我有一个按订阅出售的产品清单。价格因地区而异(大约15个地区)。我正在尝试查找当天价格最接近的产品(而不是当天最便宜的产品)。我的数据看起来像这样

data = [['29/10/20', 400, 300, 2, 1], 
       ['29/10/20', 250, 400, 1, 2], 
       ['29/10/20', 600, 600, 3, 3],
       ['30/10/20', 800, 500, 3, 2]
       ['30/10/20', 200, 800, 1, 3], 
       ['30/10/20', 550, 300, 2, 1] 

df = pd.DataFrame(data, columns = ['date', 'east price', 'west price', 'east position', 'west position'])

我希望我的输出看起来像

date     east_price nearest_east_price west_price nearest_west_price 
29/10/20 400        250                300        300 
29/10/20 250        250                400        300
29/10/20 600        400                600        400
30/10/20 800        550                500        300
30/10/20 250        250                800        500
30/10/20 550        250                300        300

我不确定是否要执行此操作,或者是否有其他方法可以执行此操作。我整天都被困住了。我也有那天最便宜的产品的问题,我希望它能返回其价值。有人可以帮忙吗?我是编程新手,所以可能会错过显而易见的东西

1 个答案:

答案 0 :(得分:1)

编辑:(2020年7月2日)。 OP需要输出,因此,如果存在重复的价格,则最接近的价格不能相同。

请参见下面的新解决方案,其中添加了np.wherebfill()

import pandas as pd
import numpy as np
data = [['29/10/20', 400, 300, 2, 1], 
       ['29/10/20', 250, 400, 1, 2], 
       ['29/10/20', 600, 600, 3, 3],
       ['30/10/20', 800, 500, 3, 2],
       ['30/10/20', 200, 800, 1, 3], 
       ['30/10/20', 550, 300, 2, 1]]

df = pd.DataFrame(data, columns = ['date', 'east_price', 'west_price', 'east_position', 'west_position'])

for col in df.columns:
    if '_price' in col:
        df = df.sort_values(col)
        nearest_col = f'nearest_{col}'
        df[nearest_col] = (np.where((df.shift(-1)[col] == df[col]), np.nan, df.shift(-1)[col]))
        df[nearest_col] = df[nearest_col].bfill()
df

输出:

    date        east price  west price  east position   west position   nearest_east_price  nearest_west_price
0   29/10/20    400        300          2               1               550.0   400.0
5   30/10/20    550        300          2               1               600.0   400.0
1   29/10/20    250        400          1               2               400.0   500.0
3   30/10/20    800        500          3               2               NaN     600.0
2   29/10/20    600        600          3               3               800.0   800.0
4   30/10/20    200        800          1               3               250.0   NaN

(旧答案)

只需使用.sort_values()进行排序,并使用.shift与下一行进行比较。

data = [['29/10/20', 400, 300, 2, 1], 
       ['29/10/20', 250, 400, 1, 2], 
       ['29/10/20', 600, 600, 3, 3],
       ['30/10/20', 800, 500, 3, 2],
       ['30/10/20', 200, 800, 1, 3], 
       ['30/10/20', 550, 300, 2, 1]]

df = pd.DataFrame(data, columns = ['date', 'east_price', 'west_price', 'east_position', 'west_position'])

解决方案#1

df = df.sort_values('east_price')
df['nearest_east_price'] = df.shift(-1)['east_price']
df = df.sort_values('west_price')
df['nearest_west_price'] = df.shift(-1)['west_price']
df

解决方案2-更好的是,如果您有许多列的列名称与其模式相似,则可以基于相似的名称遍历该列,并采用这种方式:

for col in df.columns:
    if '_price' in col:
        df = df.sort_values(col)
        nearest_col = f'nearest_{col}'
        df[nearest_col] = df.shift(-1)[col]

解决方案3:合并解决方案2:

for col in df.columns:
    if '_price' in col: df[f'nearest_{col}'] = df.sort_values(col).shift(-1)[col]
df

输出:

    date        east price  west price  east position   west position   nearest_east_price  nearest_west_price
0   29/10/20    400        300          2               1               550.0   300.0
5   30/10/20    550        300          2               1               600.0   400.0
1   29/10/20    250        400          1               2               400.0   500.0
3   30/10/20    800        500          3               2               NaN     600.0
2   29/10/20    600        600          3               3               800.0   800.0
4   30/10/20    200        800          1               3               250.0   NaN