Найти ближайшие действительные числа среди пропущенных значений в кадре данных панд - PullRequest
0 голосов
/ 11 декабря 2018

У меня есть набор данных с несколькими пропущенными последовательностями различной длины, где я хотел бы найти первые действительные числа, которые встречаются до и после этих последовательностей для определенных дат.В приведенном ниже примере набора данных я хотел бы найти действительные числа для ColumnB, которые находятся ближе всего к дате 2018-11-26.

Пример данных:

Date         ColumnA   ColumnB
2018-11-19   107.00      NaN
2018-11-20   104.00      NaN
2018-11-21   106.00      NaN
2018-11-22   105.24    80.00
2018-11-23   104.63      NaN
2018-11-26   104.62      NaN
2018-11-28   104.54      NaN
2018-11-29   103.91    86.88
2018-11-30   103.43      NaN
2018-12-01   106.13      NaN
2018-12-02   110.83      NaN

Ожидаемый результат:

[80, 86.88]

Некоторые детали:

Если бы это был тот случай, когда эта конкретная последовательность была единственной с пропущенными значениями, я бы смог решить ее, используя For Loops, или функции панд first_valid_index() или isnull(), как описано в Панды - найдите первое ненулевое значение в столбце , но это будет редко.

Я могу решить эту проблему, используя несколько For Loops, но это очень медленно длябольшие наборы данных и не очень элегантные, поэтому я бы очень хотел услышать другие предложения!

Ответы [ 5 ]

0 голосов
/ 11 декабря 2018

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

t = '2018-11-26'

Ищите индекс даты t:

ix = df.loc[df.Date==t].index.values[0]

Сохраняйте позиции ненулевых значений в ColumnB:

non_nulls = np.where(~df.ColumnB.isnull())[0]

Получите ближайшие ненулевые значения как сверху, так и снизу:

[df.loc[non_nulls[non_nulls < ix][-1],'ColumnB']] + [df.loc[non_nulls[non_nulls > ix][0],'ColumnB']]

[80.0, 86.88]
0 голосов
/ 11 декабря 2018
[df['ColumnB'].ffill().loc['2018-11-26'], df['ColumnB'].bfill().loc['2018-11-26']]
0 голосов
/ 11 декабря 2018

Вы можете использовать ffill и bfill, чтобы создать два столбца со значением до и после, например

df['before'] = df.ColumnB.ffill()
df['after'] = df.ColumnB.bfill()

, а затем получить значение для желаемых дат с помощью loc

print (df.loc[df.Date == pd.to_datetime('2018-11-26'),['before','after']].values[0].tolist())
[80.0, 86.88]

и если у вас есть список дат, вы можете использовать isin:

list_dates = ['2018-11-26','2018-11-28']
print (df.loc[df.Date.isin(pd.to_datetime(list_dates)),['before','after']].values.tolist())
[[80.0, 86.88], [80.0, 86.88]]
0 голосов
/ 11 декабря 2018

Я бы попробовал это так:

import pandas as pd
import numpy as np

df_vld = df.dropna()

idx = np.argmin(abs(df_vld.index - pd.datetime(2018, 11,26)))
# 1

df_vld.loc[df_vld.index[idx]]
Out:
ColumnA    103.91
ColumnB     86.88
Name: 2018-11-29 00:00:00, dtype: float64
0 голосов
/ 11 декабря 2018

Попробуйте так, получите индекс и срез, чтобы получить первое действительное число

idx= np.where(df['Date']=='2018-11-26')[0][0]
# idx 3

num = (df.loc[df.loc[:idx,'ColumnB'].first_valid_index(),'ColumnB'],
       df.loc[df.loc[idx:,'ColumnB'].first_valid_index(),'ColumnB'])

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