Условное выражение If применяется к кадру данных

Я пытаюсь выполнить итерацию питоническим способом (т.е. без цикла) через фрейм данных, чтобы создать новые столбцы в зависимости от того, было ли выполнено условие. В частности, учитывая фрейм данных ежедневной доходности, я хотел бы создать новый столбец, который сообщает мне, был ли превышен верхний или нижний предел (предел симметричен, но специфичен для акций, поэтому каждая строка может иметь другой предел, называемый std в df ниже), что-то вроде этого:

import pandas as pd
dict = [
        {'ticker':'jpm','date': '2016-11-28','returns': '0.2','returns2': '0.3','std': '0.1'},
{ 'ticker':'ge','date': '2016-11-28','returns': '0.2','returns2': '0.3','std': '0.1'},
{'ticker':'fb', 'date': '2016-11-28','returns': '0.2','returns2': '0.3','std': '0.1'},
{'ticker':'aapl', 'date': '2016-11-28','returns': '0.2','returns2': '0.3','std': '0.1'},
{'ticker':'msft','date': '2016-11-28','returns': '0.2','returns2': '0.3','std': '0.1'},
{'ticker':'amzn','date': '2016-11-28','returns': '0.2','returns2': '0.3','std': '0.1'},
{'ticker':'jpm','date': '2016-11-29','returns': '0.2','returns2': '0.3','std': '0.1'},
{'ticker':'ge', 'date': '2016-11-29','returns': '0.2','returns2': '0.3','std': '0.1'},
{'ticker':'fb','date': '2016-11-29','returns': '0.2','returns2': '0.3','std': '0.1'},
{'ticker':'aapl','date': '2016-11-29','returns': '0.2','returns2': '0.3','std': '0.1'},
{'ticker':'msft','date': '2016-11-29','returns': '0.2','returns2': '0.3','std': '0.1'},
{'ticker':'amzn','date': '2016-11-29','returns': '0.2','returns2': '0.3','std': '0.1'}
]
df = pd.DataFrame(dict)
df['date']      = pd.to_datetime(df1['date'])
df=df.set_index(['date','ticker'], drop=True)  

Это должно быть преобразовано так, чтобы я получил новый столбец, содержащий доход за соответствующий день, если верхний/нижний порог был превышен, если он не был превышен, он должен просто содержать доход за последний день (поэтому возвращается2).

dict2 = [
        {'ticker':'jpm','date': '2016-11-28','returns': '0.2','returns2': '-0.3','std': '0.1','sl': '0.2'},
{ 'ticker':'ge','date': '2016-11-28','returns': '-0.2','returns2': '0.3','std': '0.1','sl': '-0.2'},
{'ticker':'fb', 'date': '2016-11-28','returns': '0.05','returns2': '-0.3','std': '0.1','sl': '-0.3'},
{'ticker':'aapl', 'date': '2016-11-28','returns': '-0.2','returns2': '0.3','std': '0.1','sl': '-0.2'},
{'ticker':'msft','date': '2016-11-28','returns': '0.2','returns2': '-0.3','std': '0.1','sl': '0.2'},
{'ticker':'amzn','date': '2016-11-28','returns': '-0.2','returns2': '0.3','std': '0.1','sl': '-0.2'},
{'ticker':'jpm','date': '2016-11-29','returns': '0.2','returns2': '-0.3','std': '0.1','sl': '0.2'},
{'ticker':'ge', 'date': '2016-11-29','returns': '-0.2','returns2': '0.3','std': '0.1','sl': '-0.2'},
{'ticker':'fb','date': '2016-11-29','returns': '0.2','returns2': '-0.3','std': '0.1','sl': '0.2'},
{'ticker':'aapl','date': '2016-11-29','returns': '-0.2','returns2': '0.3','std': '0.1','sl': '-0.2'},
{'ticker':'msft','date': '2016-11-29','returns': '0.2','returns2': '-0.3','std': '0.1','sl': '0.2'},
{'ticker':'amzn','date': '2016-11-29','returns': '-0.2','returns2': '0.3','std': '0.1','sl': '-0.2'}
]
df2 = pd.DataFrame(dict2)
df2['date']      = pd.to_datetime(df2['date'])
df2=df2.set_index(['date','ticker'], drop=False)   

Я пытаюсь сохранить это гибким (чтобы он работал более чем с двумя столбцами с возвратом) и эффективным (чтобы он работал на очень больших dfs.

Может ли кто-нибудь предложить подход?

dict — это встроенный тип данных, лучше назовите его как-нибудь по-другому.
Will 30.05.2019 09:04

@Tartaglia показывает несколько строк с ожидаемым результатом

Zaraki Kenpachi 30.05.2019 09:14

Можете ли вы снова объяснить столбцы в df2? Что такое «сл»?

Will 30.05.2019 09:32
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
3
60
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Я бы использовал numpy:

dict1 = [
        {'ticker':'jpm','date': '2016-11-28','returns': '0.2','returns2': '-0.3','std': '0.1','sl': '0.2'},
{ 'ticker':'ge','date': '2016-11-28','returns': '-0.2','returns2': '0.3','std': '0.1','sl': '-0.2'},
{'ticker':'fb', 'date': '2016-11-28','returns': '0.05','returns2': '-0.3','std': '0.1','sl': '-0.3'},
{'ticker':'aapl', 'date': '2016-11-28','returns': '-0.2','returns2': '0.3','std': '0.1','sl': '-0.2'},
{'ticker':'msft','date': '2016-11-28','returns': '0.2','returns2': '-0.3','std': '0.1','sl': '0.2'},
{'ticker':'amzn','date': '2016-11-28','returns': '-0.2','returns2': '0.3','std': '0.1','sl': '-0.2'},
{'ticker':'jpm','date': '2016-11-29','returns': '0.2','returns2': '-0.3','std': '0.1','sl': '0.2'},
{'ticker':'ge', 'date': '2016-11-29','returns': '-0.2','returns2': '0.3','std': '0.1','sl': '-0.2'},
{'ticker':'fb','date': '2016-11-29','returns': '0.2','returns2': '-0.3','std': '0.1','sl': '0.2'},
{'ticker':'aapl','date': '2016-11-29','returns': '-0.2','returns2': '0.3','std': '0.1','sl': '-0.2'},
{'ticker':'msft','date': '2016-11-29','returns': '0.2','returns2': '-0.3','std': '0.1','sl': '0.2'},
{'ticker':'amzn','date': '2016-11-29','returns': '-0.2','returns2': '0.3','std': '0.1','sl': '-0.2'}
]
df = pd.DataFrame(dict1)
df['date']      = pd.to_datetime(df['date'])
df=df.set_index(['date','ticker'], drop=True)

ret1 = pd.to_numeric(df.returns).values
ret2 =  pd.to_numeric(df.returns2).values
std =  pd.to_numeric(df['std']).values

mask = np.abs(ret1) >= std
out = mask*ret1 + (1-mask)*ret2
print(out)
# prints [ 0.2 -0.2 -0.3 -0.2  0.2 -0.2  0.2 -0.2  0.2 -0.2  0.2 -0.2]

#then just add the column to df:
df['my_out'] = pd.DataFrame(out, index=df.index)

Спасибо за ответ, я все еще работаю над этим ... отчитаюсь

Tartaglia 02.06.2019 18:13
Ответ принят как подходящий

Работаю на дф2.

# Make columns numeric
df2[["returns", "returns2", "std"]] = df2[["returns", "returns2", "std"]].astype(float)

# Create new column using returns2 (we'll overwrite it in . moment)
df2["output"] = df2["returns2"]
# Mask whether returns crosses std
m = df2["returns"].abs() > df2["std"]
# Overwrite that mask onto new column
df2.loc[m, "output"] = df2.loc[m, "returns"]

Если вы хотите расширить это до более чем 2 столбцов, нам нужно будет понять критерии, для которых выбрать столбец, но процесс будет таким же: вы создаете маску, соответствующую вашим критериям, и применяете ее.

Спасибо за ответ, я все еще работаю над этим ... отчитаюсь

Tartaglia 02.06.2019 18:13

Другие вопросы по теме