Как мне сопоставить столбец в кадре данных, используя вложенный словарь? - PullRequest
3 голосов
/ 02 февраля 2020

Я создал этот вложенный словарь для определенных торговых стратегий, скажем:

{'Strategy1' :{'AAPL':'Strategy1_APPLE', 'MSFT':'Strategy1_MICROSOFT'}, 'Strategy2' :{'AAPL': 'Strategy2_APPLE', 'MSFT':'Strategy2_MICROSOFT'}}

Я уже построил фрейм данных со списком сделок, которые принадлежат либо стратегии1, либо стратегии2, и создал столбец с этой информацией. , То, что я тогда пытаюсь сделать, это сопоставить значения в dict с новым столбцом, основанным как на ключе верхнего уровня (т.е. стратегии1 или стратегии2), так и на вложенном ключе (то есть AAPL или MSFT). Так что каждая отдельная сделка сопровождается правильной стратегией и тикером в одной и той же строке фрейма данных.

Таким образом, строка в фрейме данных со Strategy1 и AAPL получает значение Strategy1_APPLE в новом столбце, но Strategy2 и AAPL получает Strategy2_APPLE.

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

edit: пример

Так что в настоящее время это выглядит так

  ticker Strategies
1   AAPL  Strategy1
2   MSFT  Strategy1
3   MSFT  Strategy2
4   AAPL  Strategy1
5   MSFT  Strategy2

и желаемый результат таков:

  ticker Strategies          substrategy
1   AAPL  Strategy1      Strategy1_APPLE
2   MSFT  Strategy1  Strategy1_MICROSOFT
3   MSFT  Strategy2  Strategy2_MICROSOFT
4   AAPL  Strategy1      Strategy1_APPLE
5   MSFT  Strategy2  Strategy2_MICROSOFT

Обратите внимание, что объединение строк или что-то в этом роде не работает для моей реальной проблемы, когда имена субстратности намного сложнее

Ответы [ 4 ]

3 голосов
/ 02 февраля 2020

Я буду использовать reindex + MultiIndex, d ваш dict здесь

df['New']=pd.DataFrame(d).stack().reindex(pd.MultiIndex.from_frame(df)).values
df
  ticker Strategies                  New
1   AAPL  Strategy1      Strategy1_APPLE
2   MSFT  Strategy1  Strategy1_MICROSOFT
3   MSFT  Strategy2  Strategy2_MICROSOFT
4   AAPL  Strategy1      Strategy1_APPLE
5   MSFT  Strategy2  Strategy2_MICROSOFT
1 голос
/ 02 февраля 2020

Здесь еще один способ использования конструктора pandas .DataFrame с изменением формы и merge:

d1 = (pd.DataFrame(d).rename_axis(index='ticker',columns='Strategies')
                     .stack()
                     .rename('substrategy')
                     .reset_index())
df.merge(d1)

Вывод:

|    | ticker   | Strategies   | substrategy         |
|---:|:---------|:-------------|:--------------------|
|  0 | AAPL     | Strategy1    | Strategy1_APPLE     |
|  1 | AAPL     | Strategy1    | Strategy1_APPLE     |
|  2 | MSFT     | Strategy1    | Strategy1_MICROSOFT |
|  3 | MSFT     | Strategy2    | Strategy2_MICROSOFT |
|  4 | MSFT     | Strategy2    | Strategy2_MICROSOFT |
1 голос
/ 02 февраля 2020

используйте метод:

def get_substrategy(t,s):    
    v = mydict[s][t] 
    return v

и затем примените лямбду:

df['substrategy'] = df.apply(lambda x: foo(x['ticker'], x['Strategies']), axis=1)

желаемый результат

   ticker   Strategies  substrategy
1   AAPL    Strategy1   Strategy1_APPLE
2   MSFT    Strategy1   Strategy1_MICROSOFT
3   MSFT    Strategy2   Strategy2_MICROSOFT
4   AAPL    Strategy1   Strategy1_APPLE
5   MSFT    Strategy2   Strategy2_MICROSOFT

Примечание: обязательно попробуйте поймать в Ваша функция в том случае, если стратегия / тикер не существует

Примечание2: без функции:

df['substrategy'] = df.apply(lambda x: mydict[x['Strategies']][x['ticker']], axis=1)

, но вам нужно будет рассмотреть сценарий, когда стратегия / тикер не ' не существует.

0 голосов
/ 02 февраля 2020

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

import pandas as pd

# input nested dict in OP
source_dict = {'Strategy1' :{'AAPL':'Strategy1_APPLE', 'MSFT':'Strategy1_MICROSOFT'}, 'Strategy2' :{'AAPL': 'Strategy2_APPLE', 'MSFT':'Strategy2_MICROSOFT'}}
tmp_rows = []

# convert nested-dict to pandas friendly input format
for strategy in source_dict.keys():
    for ticker in source_dict[strategy].keys():
        substrategy = source_dict[strategy][ticker]
        tmp_rows.append({'ticker': ticker, 'Strategies': strategy, 'substrategy': substrategy})

# create output dataframe
output_dataframe = pd.DataFrame(tmp_rows)

print(output_dataframe.head(10))
...