0
0 комментариев

Добрый день.
Разбираю пример «Имена, которые давали детям в США за период с 1880 по 201О год» из книги У.Маккинни «Python и анализ данных»:
1. Скачиваю архив имён по ссылке:
http://www.ssa.gov/oact/babynames/limits.html
2. Распаковываю архив names.zip и получаю каталог, содержащий файлы с именами вида уоb1880. txt. В каждом файле находятся данные за один год, причём, включены имена, которыми были названы не менее 5 младенцев в году. Поля в каждом файле разделены запятыми, поэтому каждый из файлов можно загрузить в объект DataFrame используя метод pandas.read_csv:

import pandas as pd
    names1880 = pd.read_csv('d:\\Python Scripts\\Names\\yob1880.txt', names = ['name','sex','births'])
    print (names1880)
runfile('D:/Python Scripts/Names.py', wdir='D:/Python Scripts')
           name sex  births
0          Mary   F    7065
1          Anna   F    2604
2          Emma   F    2003
3     Elizabeth   F    1939
4        Minnie   F    1746
5      Margaret   F    1578
6           Ida   F    1472
7         Alice   F    1414
8        Bertha   F    1320
9         Sarah   F    1288
10        Annie   F    1258
11        Clara   F    1226
 
 
3. Собираю все файлы архива в единый объект DataFrame и добавляю поле "year".
Делаю это, используя метод pandas.concat:
 
 
#На данный момент 2010 - последний доступный год
    years = range (1880, 2011)
    pieces = []
    columns = ['names', 'sex', 'births']
    for year in years:
        path = 'd:\\Python Scripts\\Names\\yob%d.txt' %year
        frame = pd.read_csv(path, names = columns)
        frame['year'] = year
        pieces.append(frame)
    #Собираю все данные в один объект DataFrame
    names = pd.concat(pieces, ignore_index=True)
    #Вывожу на экран обЪект names:
    print (names)
 
    runfile('D:/Python Scripts/Names.py', wdir='D:/Python Scripts')
             names sex  births  year
0             Mary   F    7065  1880
1             Anna   F    2604  1880
2             Emma   F    2003  1880
3        Elizabeth   F    1939  1880
4           Minnie   F    1746  1880
5         Margaret   F    1578  1880
6              Ida   F    1472  1880
7            Alice   F    1414  1880
8           Bertha   F    1320  1880
9            Sarah   F    1288  1880
10           Annie   F    1258  1880
...  ..     ...   ...
1691891    Zymaire   M       5  2010
1691892     Zyonne   M       5  2010
1691893  Zyquarius   M       5  2010
1691894      Zyran   M       5  2010
1691895      Zzyzx   M       5  2010
 
[1691896 rows x 4 columns]
 
#Агрегирую на уровне года и пола, используя метод pivot_table:
    total_births = names.pivot_table ('births', 'year','sex', aggfunc=sum)
    print (total_births)
 
runfile('D:/Python Scripts/Names.py', wdir='D:/Python Scripts')
sex         F        M
year
1880    90992   110491
1881    91953   100743
1882   107847   113686
1883   112318   104627
1884   129020   114443
1885   133055   107799
1886   144533   110784
  ...      ...
2006  1899166  2053065
2007  1920231  2072975
2008  1888177  2037309
2009  1834048  1980491
2010  1774186  1915331
 
[131 rows x 2 columns]
    #Вывожу график зависимости количества родившихся младенцев от года:
    total_births.plot(title = 'Tota1 Ьirths Ьу sex and year')

Total_births

До этого момента вопросов не возникает.
А вот далее, автор предлагает вставить столбец porp, содержащий общую долю младенцев, получивших данное имя относительно общего числа родившихся, сгруппировать данные по году и полу и добавить в каждую группу новый столбец:

def add_prop (group):
        #births = group.births.astype(float) не использую по рекомендации
        #автора, т.к. работаю c Python 3.6.4
        group['prop'] = births/births.sum()
        return group
    names = names.groupby(['year'], ['sex']).apply(add_prop)
При исполнении этого кода получаю следующий traceback:
 
 
runfile('D:/Python Scripts/Names.py', wdir='D:/Python Scripts')
    Traceback (most recent call last):
 
      File "<ipython-input-3-bd0722dd22f6>", line 1, in <module>
        runfile('D:/Python Scripts/Names.py', wdir='D:/Python Scripts')
 
      File "C:\Users\GennadyVT\Anaconda3\lib\site-packages\spyder\utils\site\sitecustomize.py", line 705, in runfile
        execfile(filename, namespace)
 
      File "C:\Users\GennadyVT\Anaconda3\lib\site-packages\spyder\utils\site\sitecustomize.py", line 102, in execfile
        exec(compile(f.read(), filename, 'exec'), namespace)
 
      File "D:/Python Scripts/Names.py", line 43, in <module>
        names = names.groupby(['year'], ['sex']).apply(add_prop)
 
      File "C:\Users\GennadyVT\Anaconda3\lib\site-packages\pandas\core\generic.py", line 5159, in groupby
        axis = self._get_axis_number(axis)
 
      File "C:\Users\GennadyVT\Anaconda3\lib\site-packages\pandas\core\generic.py", line 347, in _get_axis_number
        axis = self._AXIS_ALIASES.get(axis, axis)
 
    TypeError: unhashable type: 'list'
 
Причём, ошибку формирует последняя строка кода
names = names.groupby(['year'], ['sex']).apply(add_prop)

Подскажите, пожалуйста, каким образом можно устранить причину подобной ошибки?


Добавить комментарий