Понимание словаря для расчета статистики по словарям для каждого ключа во внутренних словарях

У меня есть такой словарь:

property2region2value = {
    'countryA':{
        'a': 24,
        'b': 56,
        'c': 78
    },
    'countryB':{
        'a': 3,
        'b': 98
    },
    'countryC':{
        'a': 121,
        'b': 12121,
        'c': 12989121,
        'd':16171
    },
    'countryD':{
        'a': 123,
        'b': 1312,
        'c': 1231
    },
    'countryE':{
        'a': 1011,
        'b': 1911
    },
    'countryF'{
        'a': 1433,
        'b': 19829,
        'c': 1132,
        'd':1791
    }
}

И я пытаюсь создать несколько словарей, каждый из которых содержит определенную статистику об основном словаре (минимум, максимум, стандарт и т. д.) обо всех значениях этого свойства (a','b','c и т. д.) во всех странах (например, countryA, countryB) и т. д.

Так, например: {'a': min of 'a' across all countries, 'b': min of 'b' across all countries....} может быть одним словарем.

На данный момент я делаю огромный цикл кода, который а) неэффективен и б) не позволяет мне быстро вычислять статистику, например. используя np.min() или np.max() в качестве функций в numpy.

Как я могу использовать понимание словаря для достижения этой цели? Текущий код для расчета min и max:

for country, property2value in property2region2value.items():
    for property,value in property2value.items():
        if property not in property2rangeMax:
            property2rangeMax[property] = 0
        if property2rangeMax[property]<value:
            property2rangeMax[property]=value
        if property not in property2rangeMin:
            property2rangeMin[property] = 0
        if property2rangeMin[property]>value:
            property2rangeMin[property] = value

person Dhruv Ghulati    schedule 24.08.2016    source источник


Ответы (2)


Вы должны использовать pandas для этой задачи:

Редактировать

Панды могут помочь вам выполнить то, что вы хотите:

In [3]: pd.DataFrame(property2region2value)
Out[3]: 
   countryA  countryB  countryC  countryD  countryE  countryF
a      24.0       3.0       121     123.0    1011.0      1433
b      56.0      98.0     12121    1312.0    1911.0     19829
c      78.0       NaN  12989121    1231.0       NaN      1132
d       NaN       NaN     16171       NaN       NaN      1791

In [4]: df.apply(np.min, axis=1)
Out[4]: 
a       3.0
b      56.0
c      78.0
d    1791.0
dtype: float64

In [5]: df.apply(np.mean, axis=1)
Out[5]: 
a    4.525000e+02
b    5.887833e+03
c    3.247890e+06
d    8.981000e+03
dtype: float64

In [6]: mean_dict = df.apply(np.mean, axis=1).to_dict()

In [7]: mean_dict
Out[7]: {'a': 452.5, 'b': 5887.833333333333, 'c': 3247890.5, 'd': 8981.0}

Или, что еще проще, вы можете транспонировать DataFrame:

In [20]: df.T
Out[20]: 
               a        b           c        d
countryA    24.0     56.0        78.0      NaN
countryB     3.0     98.0         NaN      NaN
countryC   121.0  12121.0  12989121.0  16171.0
countryD   123.0   1312.0      1231.0      NaN
countryE  1011.0   1911.0         NaN      NaN
countryF  1433.0  19829.0      1132.0   1791.0

In [21]: df.T.describe()
Out[21]: 
                 a             b             c             d
count     6.000000      6.000000  4.000000e+00      2.000000
mean    452.500000   5887.833333  3.247890e+06   8981.000000
std     612.768717   8215.770187  6.494154e+06  10168.195513
min       3.000000     56.000000  7.800000e+01   1791.000000
25%      48.250000    401.500000  8.685000e+02   5386.000000
50%     122.000000   1611.500000  1.181500e+03   8981.000000
75%     789.000000   9568.500000  3.248204e+06  12576.000000
max    1433.000000  19829.000000  1.298912e+07  16171.000000

In [22]: df.T.describe().to_dict()
Out[22]: 
{'a': {'25%': 48.25,
  '50%': 122.0,
  '75%': 789.0,
  'count': 6.0,
  'max': 1433.0,
  'mean': 452.5,
  'min': 3.0,
  'std': 612.76871656441472},
 'b': {'25%': 401.5,
  '50%': 1611.5,
  '75%': 9568.5,
  'count': 6.0,
  'max': 19829.0,
  'mean': 5887.833333333333,
  'min': 56.0,
  'std': 8215.770187065038},
 'c': {'25%': 868.5,
  '50%': 1181.5,
  '75%': 3248203.5,
  'count': 4.0,
  'max': 12989121.0,
  'mean': 3247890.5,
  'min': 78.0,
  'std': 6494153.687626767},
 'd': {'25%': 5386.0,
  '50%': 8981.0,
  '75%': 12576.0,
  'count': 2.0,
  'max': 16171.0,
  'mean': 8981.0,
  'min': 1791.0,
  'std': 10168.195513462553}}

А если вам нужен более точный контроль, вы можете выбирать:

In [24]: df.T.describe().loc[['mean','std','min','max'],:]
Out[24]: 
                a             b             c             d
mean   452.500000   5887.833333  3.247890e+06   8981.000000
std    612.768717   8215.770187  6.494154e+06  10168.195513
min      3.000000     56.000000  7.800000e+01   1791.000000
max   1433.000000  19829.000000  1.298912e+07  16171.000000

In [25]: df.T.describe().loc[['mean','std','min','max'],:].to_dict()
Out[25]: 
{'a': {'max': 1433.0,
       'mean': 452.5,
       'min': 3.0,
       'std': 612.76871656441472},
 'b': {'max': 19829.0,
       'mean': 5887.833333333333,
       'min': 56.0,
       'std': 8215.770187065038},
 'c': {'max': 12989121.0,
       'mean': 3247890.5,
       'min': 78.0,
       'std': 6494153.687626767},
 'd': {'max': 16171.0,
       'mean': 8981.0,
       'min': 1791.0,
       'std': 10168.195513462553}}

Из исходного ответа

Тогда вы можете очень легко добиться всего, чего хотите:

In [8]: df.apply(np.min)
Out[8]: 
countryA      24.0
countryB       3.0
countryC     121.0
countryD     123.0
countryE    1011.0
countryF    1132.0
dtype: float64

In [9]: df.apply(np.max)
Out[9]: 
countryA          78.0
countryB          98.0
countryC    12989121.0
countryD        1312.0
countryE        1911.0
countryF       19829.0
dtype: float64

In [10]: df.apply(np.std)
Out[10]: 
countryA    2.217105e+01
countryB    4.750000e+01
countryC    5.620356e+06
countryD    5.424170e+02
countryE    4.500000e+02
countryF    7.960893e+03
dtype: float64

Вы даже можете легко вернуть все обратно в словари:

In [11]: df.apply(np.min).to_dict()
Out[11]: 
{'countryA': 24.0,
 'countryB': 3.0,
 'countryC': 121.0,
 'countryD': 123.0,
 'countryE': 1011.0,
 'countryF': 1132.0}

Сходить с ума! Все ваши потребности в обработке данных будут проще:

In [12]: df.describe()
Out[12]: 
        countryA   countryB      countryC     countryD     countryE  \
count   3.000000   2.000000  4.000000e+00     3.000000     2.000000   
mean   52.666667  50.500000  3.254384e+06   888.666667  1461.000000   
std    27.153882  67.175144  6.489829e+06   664.322462   636.396103   
min    24.000000   3.000000  1.210000e+02   123.000000  1011.000000   
25%    40.000000  26.750000  9.121000e+03   677.000000  1236.000000   
50%    56.000000  50.500000  1.414600e+04  1231.000000  1461.000000   
75%    67.000000  74.250000  3.259408e+06  1271.500000  1686.000000   
max    78.000000  98.000000  1.298912e+07  1312.000000  1911.000000   

           countryF  
count      4.000000  
mean    6046.250000  
std     9192.447602  
min     1132.000000  
25%     1357.750000  
50%     1612.000000  
75%     6300.500000  
max    19829.000000  
person juanpa.arrivillaga    schedule 24.08.2016
comment
это не то, что я искал - я искал не минимум для каждой страны, а среднее значение для каждой метки ("a", "b", "c" и т. д.) - person Dhruv Ghulati; 24.08.2016

Несомненно, pandas — хороший выбор для этой задачи, в то время как простым способом Python вы можете просто собрать все значения для каждого свойства в одном цикле.

from collections import defaultdict

xs = defaultdict(list)

for _, vs in property2region2value.items():
    for k, v in vs.items():
        xs[k].append(v)

# xs: defaultdict(<type 'list'>, {'a': [3, 121, 24, 1433, 123, 1011], 'c': [12989121, 78, 1132, 1231], 'b': [98, 12121, 56, 19829, 1312, 1911], 'd': [16171, 1791]})

Затем вы можете применить статику к каждому элементу.

person citaret    schedule 24.08.2016