Сложные вложенные словари

#python-3.x #csv #dictionary

#python-3.x #csv #словарь

Вопрос:

Проблема, с которой я сталкиваюсь, заключается в том, что я не могу понять, почему мой код выводится не так, как я хочу. Возможно, это связано с моим пониманием словарей или логики в моем коде. Может кто-нибудь предложить помощь в том, как я могу получить эти вложенные словари? ССЫЛКА НА CSV: https://docs.google.com/document/d/1v68_QQX7Tn96l-b0LMO9YZ4ZAn_KWDMUJboa6LEyPr8/edit?usp=sharing

 import csv
data_by_region = {}
data_by_country = {}
answers = []
data = []

countries = False
f = open('dph_SYB60_T03_Population Growth, Fertility and Mortality Indicators.csv')

reader = csv.DictReader(f)

for line in reader:
  #This gets all the values into a standard dict
  data.append(dict(line))  

#This will loop thru the dict and create variables to hold specific items
for i in data: 
  # collects all of the Region/Country/Area
  places = i['Region/Country/Area'] 
  # Gets All the Years
  years = i['Year']
  i_d = i['ID']
  info = i['Footnotes']
  series = i['Series']
  value = float(i['Value'])
  # print(series)
  stats = {i['Series']:i['Value']}
  # print(stats)


  if (i['ID']== '4'):
    countries = True
  if countries == True:
    if places not in data_by_country:
      data_by_country[places] = {}
    if years not in data_by_country:
      data_by_country[places][years] = {}
      data_by_country[places][years].update(stats)
    # if series not in data_by_country:
    #   data_by_country[places][years][series] = {}
    # if value not in data_by_country:
    #   data_by_country[places][years][series] = value
  else:
    if places not in data_by_region:
      data_by_region[places] = {}
    if years not in data_by_region:
      data_by_region[places][years] = {}
      data_by_region[places][years] = stats
    # if series not in data_by_region:
    #   data_by_region[places][series] = series
    # # if value not in data_by_region:
    #   data_by_region[places][years][series] = value


print(data_by_region['Western Africa'])
  

Данные, которые я выводю в приведенном выше коде, не совпадают.
введите описание изображения здесь
Результат, к которому я стремлюсь, это :

 "Western Africa" : {
2005: {
    "Population annual rate of increase (percent)": 2.6,
"Total fertility rate (children per women)": 6,
"Infant mortality for both sexes (per 1,000 live births)": 95.7,
"Life expectancy at birth for both sexes (years)": 49.3,
"Life expectancy at birth for males (years)": 48.4,
"Life expectancy at birth for females (years)": 50.2
},
2010: { 
    <data>
    },
2015: {
    <data>
    }
  

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

1. Как выглядит текущий вывод?

2. Я добавил скриншот вывода @mypetlion

Ответ №1:

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

Например, вы можете прочитать свой файл таким образом:

 import pandas as pd
filename = 'dph_SYB60_T03_Population Growth, Fertility and Mortality Indicators.csv'
df = pd.read_csv(filename)
  

В вашем случае вам также необходимо добавить «,» в качестве разделителя тысяч:

 df = pd.read_csv(filename, thousands=r',')
  

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

Вы можете получить все данные для идентификатора:

 df[df['ID'] == 4]
  

Или по определенному региону.

 wa = df[df['Region/Country/Area'] == 'Western Africa']
  

введите описание изображения здесь

Или вы можете перебирать все уникальные значения:

 unique_regions = df['Region/Country/Area'].unique()
  

С помощью этого вложенного фрейма данных вы можете создать сводную таблицу таким образом:

 wa1 = pd.pivot_table(wa, index='Year', columns='Series', values='Value')
  

введите описание изображения здесь

Затем вы можете преобразовать этот новый фрейм данных в словарь:

 values = wa1.to_dict('records')
  

И получите список индексов с

 indexes = wa1.index
  

Эти два списка можно использовать для создания словаря для каждого региона:

 d = {key: value for (key, value) in zip(indexes, values)}

{2005: {'Infant mortality for both sexes (per 1,000 live births)': 95.700000000000003,
'Life expectancy at birth for both sexes (years)': 49.299999999999997,
'Life expectancy at birth for females (years)': 50.200000000000003,
'Life expectancy at birth for males (years)': 48.399999999999999,
'Population annual rate of increase (percent)': 2.6000000000000001,
'Total fertility rate (children per women)': 6.0},

2010: {'Infant mortality for both sexes (per 1,000 live births)': 82.700000000000003,
'Life expectancy at birth for both sexes (years)': 52.299999999999997,
'Life expectancy at birth for females (years)': 53.200000000000003,
'Life expectancy at birth for males (years)': 51.5,
'Population annual rate of increase (percent)': 2.7000000000000002,
'Total fertility rate (children per women)': 5.7999999999999998},

2015: {'Infant mortality for both sexes (per 1,000 live births)': 70.5,
'Life expectancy at birth for both sexes (years)': 54.700000000000003,
'Life expectancy at birth for females (years)': 55.600000000000001,
'Life expectancy at birth for males (years)': 53.899999999999999,
'Population annual rate of increase (percent)': 2.7000000000000002,
'Total fertility rate (children per women)': 5.5}}
  

И, наконец, вы можете использовать другой цикл для создания списка или словаря с элементом для каждого региона.

Краткие сведения

В качестве резюме вы можете сократить свой код с помощью pandas до:

 import pandas as pd
filename = 'dph_SYB60_T03_Population Growth, Fertility and Mortality Indicators.csv'
df_total = pd.read_csv(filename, thousands=r',')
regions = df_total['Region/Country/Area'].unique()
out = {}
for reg in regions:
    df_region = df_total[df_total['Region/Country/Area'] == reg]
    pivot = df_region.pivot_table(index='Year', columns='Series', values='Value')
    values_by_year = pivot.to_dict('records') 
    data_reg = {key: value for (key, value) in zip(pivot.index, values_by_year)}
    out[reg] = data_reg
out
  

В этом коде есть выход с вложенными словарями, которые вы ищете.

 {'Afghanistan': {2005: {'Infant mortality for both sexes (per 1,000 live births)': 89.5,
                        'Life expectancy at birth for both sexes (years)': 56.899999999999999,
                        'Life expectancy at birth for females (years)': 58.100000000000001,
                        'Life expectancy at birth for males (years)': 55.799999999999997,
                        'Maternal mortality ratio (deaths per 100,000 population)': 821.0,
                        'Population annual rate of increase (percent)': 4.4000000000000004,
                        'Total fertility rate (children per women)': 7.2000000000000002},
                 2010: {'Infant mortality for both sexes (per 1,000 live births)': 76.700000000000003,
                        'Life expectancy at birth for both sexes (years)': 60.0,
                        'Life expectancy at birth for females (years)': 61.299999999999997,
                        'Life expectancy at birth for males (years)': 58.899999999999999,
                        'Maternal mortality ratio (deaths per 100,000 population)': 584.0,
                        'Population annual rate of increase (percent)': 2.7999999999999998,
                        'Total fertility rate (children per women)': 6.4000000000000004},
                 2015: {'Infant mortality for both sexes (per 1,000 live births)': 68.599999999999994,
                        'Life expectancy at birth for both sexes (years)': 62.299999999999997,
                        'Life expectancy at birth for females (years)': 63.5,
                        'Life expectancy at birth for males (years)': 61.100000000000001,
                        'Maternal mortality ratio (deaths per 100,000 population)': 396.0,
                        'Population annual rate of increase (percent)': 3.2000000000000002,
                        'Total fertility rate (children per women)': 5.2999999999999998}},
 'Africa': <DATA>,
 .
 .
 . 
 'Zimbabwe': <DATA>}