Проблемы с созданием многоуровневого словаря с помощью цикла for

#python #list #dictionary #for-loop #nested

#python #Список #словарь #for-цикл #вложенный

Вопрос:

Вот мой код:

 dDict = {'Managers':colnames}


for elements in range(len(colnames)):
    dDict.update({'Managers' : {str(colnames[elements]): {str([[item for item in row] for row in sarr[elements]]) : {str([[num for num in r] for r in varr[elements]])}}}})
print(dDict)   

 

colnames — это список из 71 имени менеджера активов. sarr — это список символов, varr — это список значений, связанных с каждым символом. Список символов представляет собой список списков, где каждый список содержит список символов, связанных с менеджером активов. Я пытаюсь создать многоуровневый словарь, который упорядочивает все это в соответствующем порядке.

Это мой вывод:

 {'Managers': {"['Yacktman Asset Management']": {"[['P', 'E', 'P'], ['S', 'Y', 'Y'], ['P', 'G'], ['D', 'I', 'S'], ['M', 'S', 'F', 'T'], ['G', 'O', 'O', 'G'], ['N', 'W', 'S', 'A'], ['B', 'K', 'N', 'G'], ['C', 'T', 'S', 'H'], ['K', 'O']]": {"[['5', '.', '9', '5', '%'], ['5', '.', '4', '4', '%'], ['5', '.', '4', '1', '%'], ['5', '.', '2', '8', '%'], ['5', '.', '0', '7', '%'], ['5', '.', '0', '3', '%'], ['4', '.', '7', '6', '%'], ['4', '.', '5', '1', '%'], ['4', '.', '4', '2', '%'], ['4', '.', '3', '4', '%']]"}}}}
 

Как вы можете видеть, печатается только мой последний элемент colname, поэтому обновление является ошибкой, доступ к элементам каждого списка осуществляется странным образом («[[‘P’, ‘E’, ‘P’],), и они не связаны между собой ключ / значение.

Как мне вернуть результат:

 {'Managers': {"Yacktman Asset Management": 
             {"PEP : 5.95%", 
              "SYY : 5.44%", etc.}}
             {"AKO Capital":
             {"LIN : 12.44%",
              "BKNG : 7.88%", etc.}} } 
 

Следующее было бы еще лучше, если это возможно-

 {'Managers': {"Yacktman Asset Management": 
             {"PEP" : {"5.95%", "additional value"}, 
              "SYY" : {"5.44%", "add val"}, etc.}}
             {"AKO Capital":
             {"LIN" : {"12.44%", "add val"}
              "BKNG" : {"7.88%", "add val"}, etc.}} } 
 

Я надеюсь, что этот вопрос не слишком простой / элементарный — я некоторое время ломал голову над этим, и я был бы очень признателен, если бы мог получить некоторую помощь, потому что я уверен, что это скорее семантическая проблема, чем что-либо еще. Для получения дополнительной информации о моей конечной цели — я пытаюсь создать многоиндексный фрейм данных Pandas на основе этого словаря. Если есть лучший / более простой способ сделать это, учитывая три списка, пожалуйста, дайте мне знать.

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

1. Если ваша переменная sarr представляет собой список строк, то [[item for item in row] for row in sarr[elements]] она займет строку в позиции element (скажем, «MSFT»), а затем составит список каждой строки (скажем, «M», «S»,»F», «T»).

2. @Kris Спасибо. Что бы я использовал вместо [item for item in row] доступа LIN , скажем, [[PEP,SYY],[LIN,BKNG]] из? Если бы я делал это вне цикла, это было бы просто sarr[1][1] — как это делается в понимании списка? При обращении sarr[elements] к нему возвращается [PEP,SYY] .

3. Не могли бы вы дать мне образец каждого списка, чтобы я мог видеть, с чем вы работаете? Я чувствую, что есть лучший способ достичь вашей конечной цели — фрейма данных pandas.

4. @Kris спасибо за ваш ответ — я нашел способ решить свою проблему и создать фрейм данных, который я добавил в качестве ответа. Однако, если вы все еще заинтересованы, я также включил в свой ответ пример кода для каждого списка и некоторую информацию о том, как я получил эти данные.

Ответ №1:

Ваш ответ великолепен, но мне нравится позволять pandas выполнять как можно больше тяжелой работы, когда дело доходит до подобных вещей. Например, следующее также должно хорошо работать.

 df_combined = pd.DataFrame()
for i,name in enumerate(colnames):
    df = pd.DataFrame()
    df['Tickers'] = sarr[i]
    df['Values'] = varr[i]
    df['Fund Names'] = name*len(sarr[i])
    df_combined = pd.concat([df_combined,df])
df_combined = df_combined.groupby(['Fund Names','Tickers']).first()
df_combined
 

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

1. Это имеет гораздо больше смысла и, безусловно, является гораздо более простым решением. Я не знал, что groupby может работать таким образом. Спасибо!

Ответ №2:

 varr = np.array(vals, dtype='object')

sarr = np.array(symbol, dtype='object')

zarr = []

bigDic = {}

for x in range(len(varr)):

        zarr.append(list(zip(sarr[x],varr[x])))

def convert(a):

        it = iter(a)

        res_dct = dict(it)

        return res_dct

for x in range(len(zarr)):

        bigDic[(colnames[x][0])] = convert(zarr[x])

dfB = pd.DataFrame.from_dict(bigDic, orient="index").stack()

display(dfB)
 

И вот несколько примеров данных, с которыми я работаю, если у кого-нибудь есть лучшее решение для построения мультииндекса из этих данных.
вывод print(sarr, varr, colnames)

массив списков sarr (символы тикера):

 [array(['LIN', 'BKNG', 'EBAY', 'V', 'EL', 'GOOG', 'NKE', 'RACE', 'OTIS',
       'PG'], dtype=object)
 array(['GRA', 'WRK', 'RL', 'UNVR', 'EPC', 'OI', 'LEA', 'AVT', 'EMN',
       'NOMD'], dtype=object)
 array(['BRK.B', 'WM', 'CAT', 'CNI', 'WMT', 'ECL', 'CCI', 'FDX', 'UPS',
       'SDGR'], dtype=object)
 array(['LOW', 'CMG', 'QSR', 'HLT', 'A', 'SBUX', 'HHC'], dtype=object)
 array(['FTCH', 'DXC', 'AMZN', 'DM', 'SFIX', 'OMF', 'ADT', 'FB', 'BABA',
       'VRM'], dtype=object)
 array(['CBRE', 'GOOGL', 'ALLY', 'CHTR', 'C', 'FB', 'BAC', 'STZ', 'COF',
       'NFLX'], dtype=object)
 array(['JOE', 'BAC', 'BRK.B', 'CNQ', 'T', 'KMI', 'CINF', 'ENB', 'WES',
       'CVS'], dtype=object)
 array(['IEP', 'OXY', 'CVI', 'HLF', 'LNG', 'NWL', 'NAV', 'CLDR', 'XRX',
       'HRI'], dtype=object)
 array(['MSGE', 'VIAC', 'GS', 'LAZ', 'ORCL', 'SNA', 'NLSN', 'MOS', 'ZBH',
       'WU'], dtype=object)
 array(['NEM', 'BRK.B', 'LKQ', 'BRK.A', 'WU', 'WFC', 'ATGE', 'GOLD', 'CDK',
       'SINA'], dtype=object)]
 

Массив значений, связанных с тикерами, varr:

 [array(['12.44%', '7.88%', '7.12%', '6.59%', '5.40%', '4.84%', '4.63%',
       '4.32%', '4.06%', '3.96%'], dtype=object)
 array(['18.95%', '14.69%', '11.70%', '11.51%', '10.72%', '10.63%',
       '9.29%', '8.01%', '3.35%', '1.15%'], dtype=object)
 array(['43.71%', '9.84%', '9.18%', '8.35%', '7.49%', '4.23%', '3.80%',
       '3.52%', '3.41%', '2.47%'], dtype=object)
 array(['19.88%', '16.10%', '15.30%', '14.85%', '14.49%', '10.77%',
       '8.62%'], dtype=object)
 array(['5.16%', '4.62%', '4.29%', '4.21%', '4.17%', '3.90%', '3.30%',
       '3.24%', '3.07%', '2.87%'], dtype=object)
 array(['10.68%', '10.53%', '6.50%', '6.49%', '6.00%', '5.23%', '5.05%',
       '5.02%', '4.92%', '4.77%'], dtype=object)
 array(['90.79%', '1.19%', '1.12%', '0.93%', '0.90%', '0.70%', '0.68%',
       '0.67%', '0.62%', '0.61%'], dtype=object)
 array(['56.01%', '7.65%', '5.29%', '4.91%', '4.84%', '4.63%', '3.67%',
       '3.63%', '3.33%', '1.49%'], dtype=object)
 array(['6.38%', '5.79%', '5.47%', '5.40%', '5.20%', '5.18%', '4.92%',
       '4.47%', '4.24%', '4.19%'], dtype=object)
 array(['16.47%', '13.41%', '11.57%', '9.90%', '8.56%', '7.17%', '6.14%',
       '3.69%', '3.55%', '3.55%'], dtype=object)]
 

И, наконец, список имен фондов, он же colnames:

 [['AKO Capital'], ['Alex Roepers - Atlantic Investment Management'], ['Bill amp; Melinda Gates Foundation Trust'], ['Bill Ackman - Pershing Square Capital Management'], ['Bill Miller - Miller Value Partners'], ['Bill Nygren - Oakmark Select Fund'], ['Bruce Berkowitz - Fairholme Capital'], ['Carl Icahn - Icahn Capital Management'], ['Charles Bobrinskoy - Ariel Focus'], ['Charles de Vaulx - International Value Advisers']]