Измените длинный формат на широкий формат с двумя столбцами для каждого наблюдения в длинном формате - PullRequest
2 голосов
/ 31 марта 2019

Я пытаюсь изменить структуру данных панды со следующим длинным форматом:

ISO3    Indicator       Year    Value
FRA Pop. density        2003    113,6
FRA Pop. density        2004    114,5
FRA Pop. density        2005    115,4
USA Pop. density        2003    31,7
USA Pop. density        2004    32,0
USA Pop. density        2005    32,3
FRA Pupil-teacher ratio 2003    18,6
FRA Pupil-teacher ratio 2004    18,6
FRA Pupil-teacher ratio 2005    18,6
USA Pupil-teacher ratio 2003    14,8
USA Pupil-teacher ratio 2004    14,2
USA Pupil-teacher ratio 2005    14,1

На это:

    Pop. density            Pupil-teacher ratio 
    2003    2004    2005    2003    2004    2005
FRA 113,6   114,5   115,4   18,6    18,6    18,6
USA 31,7    32,0    32,3    14,8    14,2    14,1

Я пробовал стек и пивот, но безуспешно.

Попытка разворота:

smallstack.pivot(index='ISO3', columns=['Indicator', 'Year'], values='Value')

Результаты:

KeyError                                  Traceback (most recent call last)
<ipython-input-612-c43d9ec16c54> in <module>
----> 1 smallstack.pivot(index='ISO3', columns=['Indicator', 'Year'], values='Value')

~\Anaconda3\envs\scipy18jlab\lib\site-packages\pandas\core\frame.py in pivot(self, index, columns, values)
   5192         """
   5193         from pandas.core.reshape.reshape import pivot
-> 5194         return pivot(self, index=index, columns=columns, values=values)
   5195 
   5196     _shared_docs['pivot_table'] = """

~\Anaconda3\envs\scipy18jlab\lib\site-packages\pandas\core\reshape\reshape.py in pivot(self, index, columns, values)
    404         else:
    405             index = self[index]
--> 406         index = MultiIndex.from_arrays([index, self[columns]])
    407 
    408         if is_list_like(values) and not isinstance(values, tuple):

~\Anaconda3\envs\scipy18jlab\lib\site-packages\pandas\core\frame.py in __getitem__(self, key)
   2680         if isinstance(key, (Series, np.ndarray, Index, list)):
   2681             # either boolean or fancy integer index
-> 2682             return self._getitem_array(key)
   2683         elif isinstance(key, DataFrame):
   2684             return self._getitem_frame(key)

~\Anaconda3\envs\scipy18jlab\lib\site-packages\pandas\core\frame.py in _getitem_array(self, key)
   2724             return self._take(indexer, axis=0)
   2725         else:
-> 2726             indexer = self.loc._convert_to_indexer(key, axis=1)
   2727             return self._take(indexer, axis=1)
   2728 

~\Anaconda3\envs\scipy18jlab\lib\site-packages\pandas\core\indexing.py in _convert_to_indexer(self, obj, axis, is_setter)
   1325                 if mask.any():
   1326                     raise KeyError('{mask} not in index'
-> 1327                                    .format(mask=objarr[mask]))
   1328 
   1329                 return com._values_from_object(indexer)

KeyError: "['Year'] not in index"       

Любой совет будет высоко оценен!

Ответы [ 2 ]

0 голосов
/ 31 марта 2019

Я не уверен, если вы можете сделать оба набора столбцов за один проход пивота. Ошибка не указывает на то, что он не может найти «год», а скорее, что он не может найти «['год']». Это означает, что тип неправильный. Попробуйте что-то вроде этого, выполнив это по одному и в конце сделайте конкататацию. Вы должны будете делать это динамически, конечно, для более чем показанных категорий.


smallstack = pd.DataFrame({'ISO3': ['FRA', 'USA', 'FRA', 'USA'],
                           'Indicator': ['Pop. density', 'Pop. density', 'Pupil-teacher ratio', 'Pupil-teacher ratio'],
                           'Year': [2003, 2004, 2003, 2004],
                           'Value': [113.6, 115.6, 113.6, 115.6, ]})

pivots = [smallstack.loc[smallstack.Indicator == code].
              pivot(index='ISO3', columns='Year', values='Value')
          for code in smallstack.Indicator.unique()]
df = pd.concat(pivots, axis='columns')

0 голосов
/ 31 марта 2019

Сначала проверьте имена столбцов:

print (smallstack.columns.tolist())
['ISO3', 'Indicator', 'Year', 'Value']

А затем DataFrame.set_index с Series.unstack:

df = smallstack.set_index(['ISO3', 'Indicator', 'Year'])['Value'].unstack([1,2])
print (df)
Indicator Pop. density               Pupil-teacher ratio            
Year              2003   2004   2005                2003  2004  2005
ISO3                                                                
FRA              113,6  114,5  115,4                18,6  18,6  18,6
USA               31,7   32,0   32,3                14,8  14,2  14,1

Если нетработает, потому что дубликаты используют DataFrame.pivot_table, но сначала преобразуют столбец Value в числовое значение:

smallstack['Value'] = smallstack['Value'].str.replace(',','.').astype(float)
smallstack.pivot_table(index='ISO3', columns=['Indicator', 'Year'], values='Value')
...