найти значения col2, основанные на определенном значении col1, если нет, оставьте ближайшее значение с помощью панд - PullRequest
5 голосов
/ 16 мая 2019

У меня есть такой фрейм данных:

df
col1      col2      
 1         10
 2         15
 4         12
 5         23
 6         11
 8         32
 9         12
 11        32
 2         23
 3         21
 4         12
 6         15
 9         12
 10        32

Я хочу выбрать значения col2 для каждых 1, 5 и 10 значений col1. Если значение col1 не равно 1, 5 или 10, оставьте значения col2, где значения col1 ближе всего к 1,5 или 10

например, итоговый df будет выглядеть так:

df
col1      col2      
 1         10
 5         23
 11        32
 2         23
 6         15
 10        32

как это сделать, используя панд без всякой петли

Ответы [ 3 ]

1 голос
/ 16 мая 2019
  • df.col1.diff().lt(0).cumsum() определяет группы возрастающих значений
  • set_index с этими группами и col1, но сохраняет col1 в собственном кадре данных с drop=False
  • groupby и pd.concat для использования reindex с method='nearest'

Я оставил старый индекс col1, чтобы вы могли видеть, что сопоставлено с чем.

c = df.set_index([df.col1.diff().lt(0).cumsum().rename('grp'), 'col1'], drop=False)
pd.concat([c.xs(k).reindex([1, 5, 10], method='nearest') for k, c in c.groupby(level=0)])

      col1  col2
col1            
1        1    10
5        5    23
10      11    32
1        2    23
5        6    15
10      10    32

Если вам не нравится этот дополнительный col1 в индексе, вы можете переименовать индекс и затем удалить его:

c = df.set_index([df.col1.diff().lt(0).cumsum().rename('grp'), 'col1'], drop=False)
pd.concat([c.xs(k).reindex([1, 5, 10], method='nearest') for k, c in c.groupby(level=0)]) \
    .rename_axis(None).reset_index(drop=True)

   col1  col2
0     1    10
1     5    23
2    11    32
3     2    23
4     6    15
5    10    32
1 голос
/ 16 мая 2019

Очень похоже на метод Пира

s=df.col1.diff().lt(0).cumsum()
idx=df.reset_index().groupby(s).apply(lambda x : x.set_index('col1').reindex([1,5,10],method='nearest'))['index']
df.loc[idx]
Out[19]: 
    col1  col2
0      1    10
3      5    23
7     11    32
8      2    23
11     6    15
13    10    32

Другой способ получить индекс merge_asof

df['key']=s
import itertools
l=list(itertools.product(df.key.unique().tolist(),[1,5,10]))
mergedf=pd.DataFrame(l,columns=['key','col1']).astype(int)
df.col1=df.col1.astype('int32')
idx=pd.merge_asof(mergedf.sort_values('col1'),df.reset_index().sort_values('col1'),on='col1',by='key',direction ='nearest')['index']
1 голос
/ 16 мая 2019

Попробуйте это:

def extract_vals(x, vals=[1,5,10]):
    vals = np.array(vals)
    s = abs(x['col1'].values - vals[:,None])

    return x.iloc[s.argmin(axis=1)]

s = df.col1.diff().lt(0).cumsum()
df.groupby(s).apply(extract_vals).reset_index(drop=True)

Вывод, который отличается от вашего из-за наличия 4,6 во второй группе:

    col1    col2
0   1       10
1   5       23
2   9       12
3   2       23
4   4       12
5   10      32
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...