Как создать новый столбец, содержащий наибольшее значение в списке, которое меньше значения ячейки в существующем столбце? - PullRequest
0 голосов
/ 15 февраля 2019

У меня есть pandas dataframe, который выглядит следующим образом:

     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

Как мне этого добиться?

Ответы [ 5 ]

0 голосов
/ 15 февраля 2019

Не уверен в методе pandas, но numpy.searchsorted идеально подходит здесь.

Находит индексы, в которые следует вставлять элементы для поддержания порядка.

Когда у вас есть индексы, в которые будут вставлены ваши элементы для поддержания сортировки, вы можете посмотреть на элемент слева этих индексов в массиве поиска, чтобы найти ближайшийменьший элемент.Если элемент будет вставлен в начало списка (индекс 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)
0 голосов
/ 15 февраля 2019

Вот еще один способ сделать это:

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
0 голосов
/ 15 февраля 2019
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
0 голосов
/ 15 февраля 2019

Есть встроенная функция 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
0 голосов
/ 15 февраля 2019
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', если значения не найдены

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...