2016-02-29 4 views
2

Этот вопрос строит на предыдущий вопрос здесь: create new column that compares across rows in pandas dataframeизмерения через следующие N строки в dataframe

Я хотел бы сделать новый столбец, который проверяет, чтобы увидеть, если любой из следующих п строк отличается более чем X Например, если бы у нас был фрейм данных, а следующие 4 строки отличались более чем на 1, то новое значение было бы 0. Если следующие 4 строки отличались меньше или равными 1, тогда новое значение было бы равно 1.

>>> df = pandas.DataFrame({"A": [5,6,4,3,5]}) 
>>> df 
    A 
0 5 
1 6 
2 4 
3 3 
4 5 
>>> desired_result = pandas.DataFrame({"A": [5,6,7,8,2], "new":  [1,1,0,0,0]}) 
>>> desired_result 
    A new 
0 5 1 
1 6 0 
2 4 1 
3 3 0 
4 5 0 

В приведенном выше примере значение 5 становится равным 1, поскольку абсолютная разница между следующими двумя значениями равна < = 1 (abs (5-6) = 1 и абс (5-4) = 1).

Подобный ответ, обеспечиваемого в вышеупомянутом посте я попытался решить дело со следующим кодом:

df['new'] = 1 
df.loc[abs(df.A - df.A.shift(-1)) > 1 , 'new'] = 0 

Этот код работает при просмотре только на следующую строку, но я не уверен, что лучший способ расширить его до n строк.

ответ

1
n = 2 # Number of following rows 
x = 1 # Differ by more than 'x'. 

>>> pd.concat([(df.A - df.A.shift(-i - 1)).abs().le(x) 
       for i in range(n)], axis=1).any(axis=1) * 1 
0 1 
1 0 
2 1 
3 0 
4 0 
dtype: int64 

Смещение выполняется n раз и по сравнению с текущим значением, что приводит к следующим булевым значениям:

# shift-1 shift-2 
     A  A 
0 True True 
1 False False 
2 True True 
3 False False 
4 False False 

Эти результаты затем сравниваются по строкам, ища любое истинное значение. Наконец, логический результат умножается на единицу, чтобы превратить его в единицы и нули.

`pd.concat(...).any(axis=1) * 1` 
+0

Спасибо! Единственное изменение, которое я сделал, это использовать .all вместо .any, поскольку я хотел удостовериться, что все n значений были <= x, в отличие от любого. – reese0106

0

Вы можете использовать комбинации rolling_max и shift.

Е.Г., если период 2, а затем

df = pd.DataFrame({"A": [5,6,4,3,5]}) 
>>> pd.rolling_max(df.A.shift(-1), 2).shift(-1)  
0  6 
1  4 
2  5 
3 NaN 
4 NaN 
Name: A, dtype: float64 

дает максимум следующих 2-х периоды (обратите внимание на два NaN с в конце, где вещи просто не определены).

В общем, для окна размером k, вы будете использовать

pd.rolling_max(df.A.shift(-1), k).shift(k - 1) 

С этого момента, вы можете просто сравнить оригинальные серии, минус 1 к результату:

df.A - 1 > pd.rolling_max(... 
Смежные вопросы