как передать значение ячейки в функцию сдвига

#python #pandas #variables #shift

#python #панды #переменные #сдвиг

Вопрос:

как передать значение ячейки в фрейме данных pandas функции shift?

вот несколько примеров ввода:

 import pandas as pd
import numpy as np

df = pd.DataFrame(data={'x': [0,0,0,0,0,0,0,5,0,0],
                        'y': [np.nan,np.nan,np.nan,10,np.nan,np.nan,np.nan,np.nan,np.nan,np.nan]})

df['z'] = np.where(df['x'].shift(1) > 0, (50 - df['y'].shift(5)), np.nan)

print(df)

df['a'] = np.where(df['x'].shift(1) > 0, (50 - df['y'].shift(df['x'].shift(1).get_value())), np.nan)
  

вот результат:

    x     y     z
0  0   NaN   NaN
1  0   NaN   NaN
2  0   NaN   NaN
3  0  10.0   NaN
4  0   NaN   NaN
5  0   NaN   NaN
6  0   NaN   NaN
7  5   NaN   NaN
8  0   NaN  40.0
9  0   NaN   NaN

Traceback (most recent call last):
  File "C:stockssandp500stack overflow question 1.py", line 11, in <module>
    df['a'] = np.where(df['x'].shift(1) > 0, (50 - df['y'].shift(df['x'].shift(1).get_value())), np.nan)
TypeError: get_value() missing 1 required positional argument: 'label'
  

столбец «x» будет иметь либо значение 0, либо некоторое целое число от 1 до n. эти целые числа — это значение, которое я хочу передать функции shift для создания столбца «z». здесь, в столбце «z», я обманываю, жестко кодируя «5» в функции сдвига. столбец «a» — это моя попытка передать динамическое значение из столбца «x» в функцию сдвига.

я перепробовал десятки вариантов этого за последние 48 часов и ничего не могу заставить работать. у кого-нибудь есть идеи? заранее спасибо.

Комментарии:

1. Пожалуйста, опубликуйте ожидаемый результат для столбца a . Было бы здорово, если бы вы могли также объяснить логику его вычисления.

2. ожидаемый результат столбца «a» — это то, что в настоящее время отображается в столбце «z» = все NAN, за исключением строки 8, которая будет равна 40,0. логика заключается в том, что всякий раз, когда в столбце «x» есть ненулевое значение, следующая строка в столбце «z» — этопростое вычитание значения столбца «y» (сдвинутого на значение переменной целого числа столбца «x»).

3. Есть ли логика в этом вычислении?

Ответ №1:

Я думаю, что то, что вы пытались сделать, достижимо с df.apply :

 df = pd.DataFrame(data={'x': [0,0,0,0,0,0,0,5,0,0],
                        'y': [np.nan,np.nan,np.nan,10,np.nan,np.nan,np.nan,np.nan,np.nan,np.nan]})
  

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

 def shifter(mydf):
    offset = int(mydf['offset'])
    if offset>0:
        val = 50 - df.shift(int(offset))['y'].loc[int(mydf['index'])]
    else:
        val = np.nan
    return val    
  

Я сделал копию фрейма данных с индексом в виде столбца, а затем, поскольку вы делаете это дополнительно .shift(1) в столбце «x», я создал вспомогательный столбец с именем offset , который просто делает это заранее:

 df2 = df.reset_index()
df2['offset'] = df2['x'].shift(1).fillna(0)

print(df2)
   index  x     y  offset
0      0  0   NaN     0.0
1      1  0   NaN     0.0
2      2  0   NaN     0.0
3      3  0  10.0     0.0
4      4  0   NaN     0.0
5      5  0   NaN     0.0
6      6  0   NaN     0.0
7      7  5   NaN     0.0
8      8  0   NaN     5.0
9      9  0   NaN     0.0
  

Затем вы можете применить функцию сдвига по строкам. Обратите внимание, что он по-прежнему ссылается на df исходный фрейм данных в этой функции. Он использует значения в столбце «индекс», чтобы найти скорректированную строку .loc в исходном фрейме данных.

 df['z'] = df2.apply(shifter, axis=1)

print(df)
   x     y     z
0  0   NaN   NaN
1  0   NaN   NaN
2  0   NaN   NaN
3  0  10.0   NaN
4  0   NaN   NaN
5  0   NaN   NaN
6  0   NaN   NaN
7  5   NaN   NaN
8  0   NaN  40.0
9  0   NaN   NaN
  

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

 df = pd.DataFrame(data={'x': [0,1,3,5,2,1,0,5,0,1],
                        'y': [2.0,4,3,10,1,77,28,56,42,48]})

def simple_shifter(mydf):
    offset = int(mydf['x'])
    val = df.shift(int(offset))['y'].loc[int(mydf['index'])]
    return val    

df3 = df.reset_index()
df['y_offset_by_x'] = df3.apply(simple_shifter, axis=1)

print(df)
   x     y  y_offset_by_x
0  0   2.0            2.0
1  1   4.0            2.0
2  3   3.0            NaN
3  5  10.0            NaN
4  2   1.0            3.0
5  1  77.0            1.0
6  0  28.0           28.0
7  5  56.0            3.0
8  0  42.0           42.0
9  1  48.0           42.0
  

Конечно, если фреймы данных большие, необходимо оптимизировать скорость, но это должно сработать.