#python #arrays #python-2.7 #pandas #numpy
#python #массивы #python-2.7 #pandas #numpy
Вопрос:
В моем фрейме данных я получу столбец, который содержит всего несколько значений, отличных от nan. Я хочу использовать значения, отличные от nan, в качестве группирующих переменных для всех предыдущих строк, которые содержат значение NaN. Чтобы имитировать это, я создал следующий массив:
count = np.array([np.NaN,np.NaN,np.NaN,3,np.NaN,np.NaN,6,np.NaN,np.NaN,np.NaN,np.NaN,np.NaN,12])
count = Series(count)
Для этого массива я смог создать функцию заполнения
def pad_expsamp_time(array):
sect = np.zeros(array.size) # create array filled with zeros
inds = array.index[array.notnull()] # select the non-zero values
rev_inds = inds[::-1] # sort high to low
# fill array with value until index of value. Repeat for lower values.
for i in rev_inds:
sect[:i] = i
return Series(sect)
Эта функция работает, когда она может предположить, что индексы значений, отличных от nan, равны фактическим значениям. Однако, как я могу заполнить массив, когда индексы не равны содержимому?
Например, что, если количество массивов равно:
count = np.array([np.NaN,np.NaN,np.NaN,1,np.NaN,np.NaN,2,np.NaN,np.NaN,np.NaN,np.NaN,np.NaN,3])
И желаемый результат
count = np.array([1,1,1,1,2,2,2,3,3,3,3,3,3]
Возможно, что в конце массива есть NAN. Я бы хотел, чтобы они оставались NANS, чтобы фрейм данных игнорировал их.
count = np.array([np.NaN,np.NaN,np.NaN,1,np.NaN,np.NaN,2,np.NaN,np.NaN,3,np.NaN,np.NaN])
# Will become:
count = np.array([1,1,1,1,2,2,2,3,3,3,np.nan,np.nan]
Комментарии:
1. Может ли последний элемент быть
NaN
?2. @Divakar да, это действительно могло бы
3. Итак, вам нужно, чтобы он был чем-то заполнен? Если да, то чем мы должны его заполнить? Может быть, добавить примерный пример?
Ответ №1:
IIUC вы можете просто использовать метод pandas bfill():
ваш пример:
In [89]: s = pd.Series(np.array([np.nan,np.nan,np.nan,1,np.nan,np.nan,2,np.nan,np.nan,3,np.nan,np.nan]))
In [90]: s
Out[90]:
0 NaN
1 NaN
2 NaN
3 1.0
4 NaN
5 NaN
6 2.0
7 NaN
8 NaN
9 3.0
10 NaN
11 NaN
dtype: float64
In [91]: s.bfill()
Out[91]:
0 1.0
1 1.0
2 1.0
3 1.0
4 2.0
5 2.0
6 2.0
7 3.0
8 3.0
9 3.0
10 NaN
11 NaN
dtype: float64
Примеры Divakar:
In [81]: s = pd.Series(array([ nan, nan, nan, 6., nan, nan, 5., nan, nan, nan, nan, nan, 2.]))
In [82]: s
Out[82]:
0 NaN
1 NaN
2 NaN
3 6.0
4 NaN
5 NaN
6 5.0
7 NaN
8 NaN
9 NaN
10 NaN
11 NaN
12 2.0
dtype: float64
In [83]: s.bfill()
Out[83]:
0 6.0
1 6.0
2 6.0
3 6.0
4 5.0
5 5.0
6 5.0
7 2.0
8 2.0
9 2.0
10 2.0
11 2.0
12 2.0
dtype: float64
In [84]: s = pd.Series(array([ nan, nan, nan, 1., nan, nan, 2., nan, nan, nan, nan, nan, 3.]))
In [85]: s.bfill()
Out[85]:
0 1.0
1 1.0
2 1.0
3 1.0
4 2.0
5 2.0
6 2.0
7 3.0
8 3.0
9 3.0
10 3.0
11 3.0
12 3.0
dtype: float64
In [86]: s = pd.Series(array([ nan, nan, nan, 1., nan, nan, 2., nan, nan, 3., nan, nan]))
In [87]: s.bfill()
Out[87]:
0 1.0
1 1.0
2 1.0
3 1.0
4 2.0
5 2.0
6 2.0
7 3.0
8 3.0
9 3.0
10 NaN
11 NaN
dtype: float64
Комментарии:
1. @Divakar, ИМО, это довольно стандартная операция Pandas, так что здесь нет никакой магии 😉
2. Вау? Действительно? Все проблемы напрасны, ха-ха. Если бы я только знал раньше. Теперь я также могу прекратить писать функцию прямого заполнения…
Ответ №2:
Вот векторизованный подход —
# Append False at either sides of NaN mask as we try to find start amp;
# stop of each NaN interval by looking for rising and falling edges
mask = np.hstack((False,np.isnan(count),False))
start = np.flatnonzero(mask[1:] > mask[:-1])
stop = np.flatnonzero(mask[1:] < mask[:-1])
lens = stop - start
# Account for NaNs if any at the end of input that might throw off stop values
stop = stop.clip(max=count.size-1)
# Assign values
count[mask[1:-1]] = count[stop].repeat(lens)
Пример выполнения —
Случай # 1 :
In [103]: count
Out[103]:
array([ nan, nan, nan, 6., nan, nan, 5., nan, nan, nan, nan,
nan, 2.])
In [104]: # Listed code ...
In [105]: count
Out[105]: array([ 6., 6., 6., 6., 5., 5., 5., 2., 2., 2., 2., 2., 2.])
Случай # 2 :
In [118]: count
Out[118]:
array([ nan, nan, nan, 1., nan, nan, 2., nan, nan, nan, nan,
nan, 3.])
In [119]: # Listed code ...
In [120]: count
Out[120]: array([ 1., 1., 1., 1., 2., 2., 2., 3., 3., 3., 3., 3., 3.])
Случай # 3 :
In [114]: count
Out[114]:
array([ nan, nan, nan, 1., nan, nan, 2., nan, nan, 3., nan,
nan])
In [115]: # Listed code ...
In [116]: count
Out[116]:
array([ 1., 1., 1., 1., 2., 2., 2., 3., 3., 3., nan,
nan])
Комментарии:
1. Удивительно! Большое вам спасибо!