как изменить датафрейм в применяемых функциях панд - PullRequest
0 голосов
/ 13 июня 2019

Я хочу использовать команду apply для динамического изменения содержимого моего фрейма данных, таблица выглядит так:

   index  price signal  stoploss
0      0   1000   True     990.0
1      1   1010  False     990.0
2      2   1020   True    1010.0
3      3   1000  False    1010.0
4      4    990  False    1010.0
5      5    980  False    1010.0
6      6   1000  False    1010.0
7      7   1020   True    1010.0
8      8   1030  False    1010.0
9      9   1040  False    1010.0

мой код:

def test(row, dd):
    if row.signal:
        dd['inorder']=True
        row['stoploss']=1

    df = pd.DataFrame({'index':[0,1,2,3,4,5,6,7,8,9],
                   'price':[1000,1010,1020,1000,990,980,1000,1020,1030,1040],
                   'signal':[True, False, True, False, False, False, False, True, False, False]})


if __name__ == '__main__':
    df['stoploss'] = df.loc[df['signal'], 'price'] - 10
    df['stoploss'].ffill(inplace=True)


    xx = dict(inorder=False)
    df.apply(lambda row: test(row, xx), axis=1)
    print(df)

Когда я отслеживаю функциюtest, я вижу, что значение действительно изменяется на 1, но вне области функционального тестирования, похоже, это никак не влияет на фрейм данных.

Я пытался использовать другой способ изменения содержимогоdataframe,

for k, row in df.iterrows():
    if row.signal:
        xx['inorder'] = True
        df.loc[k, 'stoploss'] = 1

этот работает, но, очевидно, он намного медленнее, чем применяется.

Правильный результат, который я ожидаю, таков:

   index  price signal  stoploss
0      0   1000   True       1.0
1      1   1010  False     990.0
2      2   1020   True       1.0
3      3   1000  False    1010.0
4      4    990  False    1010.0
5      5    980  False    1010.0
6      6   1000  False    1010.0
7      7   1020   True       1.0
8      8   1030  False    1010.0
9      9   1040  False    1010.0

Как этого добитьсяназначение в заявке, пожалуйста?

Спасибо

1 Ответ

0 голосов
/ 13 июня 2019

Если вы посмотрите на документы для apply, вы заметите, что apply не меняет DataFrame на месте, а скорее возвращает новый фрейм данных, в котором была применена функция.

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

df = df.apply(lambda row: test(row, xx), axis=1)

Edit:

ИМО, это не очень хорошо задокументировано, но вызов df.apply(func, axis=1) будет применять func к каждой строке, а установить для строки значение, возвращаемое func.

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

df = pd.DataFrame({'index':[0,1,2,3,4,5,6,7,8,9],
                   'price':[1000,1010,1020,1000,990,980,1000,1020,1030,1040],
                   'signal':[True, False, True, False, False, False, False, True, False, False]})

df['stoploss'] = df.loc[df['signal'], 'price'] - 10
df['stoploss'].ffill(inplace=True)

def test(row):
    row.stoploss = 1 if row.signal else row.stoploss
    return row

modified_df = df.apply(test, axis=1)

Кроме того, я не думаю, что вам действительно нужно использовать apply, чтобы получить желаемый результат. Вы пробовали что-то вроде

df.loc[df['signal'] == True, 'stoploss'] = 1

Это был бы гораздо более простой и быстрый способ получить целевой результат.

...