У меня есть следующий фрейм данных:
data = [['BALANCED', 'Corp EUR'], ['YIELD', 'Corp USD'], ['GROWTH', 'HG CHF']]
df = pd.DataFrame(data, columns=['STRATEGY', 'ASSET_CLASS']
df
STRATEGY ASSET_CLASS
0 BALANCED Corp EUR
1 YIELD Corp USD
2 GROWTH HG CHF
Моя цель — присвоить определенное значение из словаря с несколькими значениями в зависимости от значения в столбце «СТРАТЕГИЯ». Словарь, содержащий различные классы активов, выглядит следующим образом:
my_dict = {'HG CHF': [5, 2, 3, 4],
'Corp EUR': [4, 6, 8, 7],
'Corp USD': [9, 7.5, 5.3, 6],
}
my_dict
{'HG CHF': [5, 2, 3, 4],
'Corp EUR': [4, 6, 8, 7],
'Corp USD': [9, 7.5, 5.3, 6]}
В словаре каждое значение обозначает определенную стратегию. В этом случае ДОХОД включает все вторые значения, СБАЛАНСИРОВАННЫЕ все третьи значения и РОСТ все четвертые значения соответственно. По сути, я хотел бы получить следующий результат:
STRATEGY ASSET_CLASS TARGET
0 BALANCED Corp EUR 8.0
1 YIELD Corp USD 7.5
2 GROWTH HG CHF 4.0
Как я могу правильно указать Python, к какому значению в словаре нужно получить доступ? Ниже команда отображает все значения:
df['TARGET'] = df['ASSET_CLASS'].map(my_dict)
STRATEGY ASSET_CLASS TARGET
0 BALANCED Corp EUR [4, 6, 8, 7]
1 YIELD Corp USD [9, 7.5, 5.3, 6]
2 GROWTH HG CHF [5, 2, 3, 4]
Любое предложение очень ценится! Заранее большое спасибо!!
Я бы реализовал функцию, основанную на
ДОХОД включает все вторые значения, СБАЛАНСИРОВАННЫЕ все третьи значения и РОСТ. все четвертые значения,
использовать с pandas.DataFrame.apply
следующим образом
import pandas as pd
def get_target_value(row):
if row.STRATEGY == "YIELD":
return row.TARGET[1]
if row.STRATEGY == "BALANCED":
return row.TARGET[2]
if row.STRATEGY == "GROWTH":
return row.TARGET[3]
data = [['BALANCED', 'Corp EUR'], ['YIELD', 'Corp USD'], ['GROWTH', 'HG CHF']]
df = pd.DataFrame(data, columns=['STRATEGY', 'ASSET_CLASS'])
my_dict = {'HG CHF': [5, 2, 3, 4],
'Corp EUR': [4, 6, 8, 7],
'Corp USD': [9, 7.5, 5.3, 6],
}
df['TARGET'] = df['ASSET_CLASS'].map(my_dict)
df['TARGET'] = df.apply(get_target_value,axis=1)
print(df)
дает результат
STRATEGY ASSET_CLASS TARGET
0 BALANCED Corp EUR 8.0
1 YIELD Corp USD 7.5
2 GROWTH HG CHF 4.0
Обратите внимание, что значения меньше на единицу по сравнению с индексирование вашего описания, как в python
list
s, начинается с 0.
Используйте второй словарь и понимание списка с помощью zip:
# which item should be picked?
nth = {'YIELD': 1, 'BALANCED': 2, 'GROWTH': 3}
df['TARGET'] = [
my_dict[a][nth[s]] for s, a in zip(df['STRATEGY'], df['ASSET_CLASS'])
]
Выход:
STRATEGY ASSET_CLASS TARGET
0 BALANCED Corp EUR 8.0
1 YIELD Corp USD 7.5
2 GROWTH HG CHF 4.0
Если есть вероятность, что в списках недостаточно элементов, вы можете добавить проверку безопасности:
# let's pick the 5th item for "GROWTH"
nth = {'YIELD': 1, 'BALANCED': 2, 'GROWTH': 5}
df['TARGET'] = [
d[n] if (n := nth[s]) < len(d := my_dict[a]) else None
for s, a in zip(df['STRATEGY'], df['ASSET_CLASS'])
]
Пример:
STRATEGY ASSET_CLASS TARGET
0 BALANCED Corp EUR 8.0
1 YIELD Corp USD 7.5
2 GROWTH HG CHF NaN
Еще один вопрос: используемый мной фрейм данных содержит значения, для которых в словаре нет соответствующих ключей, что приводит к появлению сообщения «KeyError». Есть ли способ пропустить эти записи и просто указать «Нет» в качестве значения для столбца «TARGET_DUR»?
Да, замените my_dict[a]
на my_dict.get(a, [])
во втором подходе.
Или используйте d[n] if a in my_dict and (n := nth[s]) < len(d := my_dict[a]) else None
Сопоставление и последующее применение, вероятно, будет медленным, потому что вы создаете столбец TARGET дважды (думаю, что это, вероятно, не имеет большого значения для такой маленькой выборки...). Если вы собираетесь использовать
apply
rowise, вы можете просто заставитьget_target_value
использовать значения изSTRATEGY
иASSET_CLASS
, чтобы извлечь значения непосредственно из словаря и отказаться от шага карты.