Spec-Zone.ru › pandas 0.18

Справочник

Это хранилище кратких и понятных примеров и ссылок на полезные рецепты для pandas. Мы поощряем пользователей добавлять в это руководство.

Добавление интересных ссылок и/или встроенных примеров в этот раздел — отличный первый запрос на вытягивание изменений.

По возможности были вставлены упрощенные, сжатые, понятные для новых пользователей примеры встроены, чтобы дополнить ссылки на Stack Overflow и GitHub. Многие ссылки содержат расширенную информацию, помимо того, что предлагают встроенные примеры.

Pandas (pd) и Numpy (np) — единственные два сокращенно импортированных модуля. Остальные импортируются явно для новичков.

Эти примеры написаны для python 3.4. Для более ранних версий python могут потребоваться незначительные изменения.

Идиомы

Вот некоторые интересные идиомы pandas idioms

if-then/if-then-else для одного столбца и присвоение значения одному или нескольким другим столбцам:

In [1]: df = pd.DataFrame(
   ...:      {'AAA' : [4,5,6,7], 'BBB' : [10,20,30,40],'CCC' : [100,50,-30,-50]}); df
   ...: 
Out[1]: 
   AAA  BBB  CCC
0    4   10  100
1    5   20   50
2    6   30  -30
3    7   40  -50

if-then...

An if-then для одного столбца

In [2]: df.ix[df.AAA >= 5,'BBB'] = -1; df
Out[2]: 
   AAA  BBB  CCC
0    4   10  100
1    5   -1   50
2    6   -1  -30
3    7   -1  -50

An if-then с присвоением значения двум столбцам:

In [3]: df.ix[df.AAA >= 5,['BBB','CCC']] = 555; df
Out[3]: 
   AAA  BBB  CCC
0    4   10  100
1    5  555  555
2    6  555  555
3    7  555  555

Добавить ещё одну строку с другой логикой, чтобы сделать -else

In [4]: df.ix[df.AAA < 5,['BBB','CCC']] = 2000; df
Out[4]: 
   AAA   BBB   CCC
0    4  2000  2000
1    5   555   555
2    6   555   555
3    7   555   555

Или используйте pandas where после того, как вы настроили маску

In [5]: df_mask = pd.DataFrame({'AAA' : [True] * 4, 'BBB' : [False] * 4,'CCC' : [True,False] * 2})

In [6]: df.where(df_mask,-1000)
Out[6]: 
   AAA   BBB   CCC
0    4 -1000  2000
1    5 -1000 -1000
2    6 -1000   555
3    7 -1000 -1000

if-then-else с использованием numpy’s where()

In [7]: df = pd.DataFrame(
   ...:      {'AAA' : [4,5,6,7], 'BBB' : [10,20,30,40],'CCC' : [100,50,-30,-50]}); df
   ...: 
Out[7]: 
   AAA  BBB  CCC
0    4   10  100
1    5   20   50
2    6   30  -30
3    7   40  -50

In [8]: df['logic'] = np.where(df['AAA'] > 5,'high','low'); df
Out[8]: 
   AAA  BBB  CCC logic
0    4   10  100   low
1    5   20   50   low
2    6   30  -30  high
3    7   40  -50  high

Разделение

Разделить таблицу с помощью булевого критерия

In [9]: df = pd.DataFrame(
   ...:      {'AAA' : [4,5,6,7], 'BBB' : [10,20,30,40],'CCC' : [100,50,-30,-50]}); df
   ...: 
Out[9]: 
   AAA  BBB  CCC
0    4   10  100
1    5   20   50
2    6   30  -30
3    7   40  -50

In [10]: dflow = df[df.AAA <= 5]

In [11]: dfhigh = df[df.AAA > 5]

In [12]: dflow; dfhigh
Out[12]: 
   AAA  BBB  CCC
2    6   30  -30
3    7   40  -50

Построение критериев

Выбор с помощью сложных критериев из таблицы pandas

In [13]: df = pd.DataFrame(
   ....:      {'AAA' : [4,5,6,7], 'BBB' : [10,20,30,40],'CCC' : [100,50,-30,-50]}); df
   ....: 
Out[13]: 
   AAA  BBB  CCC
0    4   10  100
1    5   20   50
2    6   30  -30
3    7   40  -50

...и (без присваивания возвращает Series)

In [14]: newseries = df.loc[(df['BBB'] < 25) & (df['CCC'] >= -40), 'AAA']; newseries
Out[14]: 
0    4
1    5
Name: AAA, dtype: int64

...или (без присваивания возвращает Series)

In [15]: newseries = df.loc[(df['BBB'] > 25) | (df['CCC'] >= -40), 'AAA']; newseries;

...или (с присвоением изменяет DataFrame.)

In [16]: df.loc[(df['BBB'] > 25) | (df['CCC'] >= 75), 'AAA'] = 0.1; df
Out[16]: 
   AAA  BBB  CCC
0  0.1   10  100
1  5.0   20   50
2  0.1   30  -30
3  0.1   40  -50

Выбор строк с данными, наиболее близкими к определённому значению, с использованием argsort

In [17]: df = pd.DataFrame(
   ....:      {'AAA' : [4,5,6,7], 'BBB' : [10,20,30,40],'CCC' : [100,50,-30,-50]}); df
   ....: 
Out[17]: 
   AAA  BBB  CCC
0    4   10  100
1    5   20   50
2    6   30  -30
3    7   40  -50

In [18]: aValue = 43.0

In [19]: df.ix[(df.CCC-aValue).abs().argsort()]
Out[19]: 
   AAA  BBB  CCC
1    5   20   50
0    4   10  100
2    6   30  -30
3    7   40  -50

Динамическое сокращение списка критериев с использованием бинарных операторов

In [20]: df = pd.DataFrame(
   ....:      {'AAA' : [4,5,6,7], 'BBB' : [10,20,30,40],'CCC' : [100,50,-30,-50]}); df
   ....: 
Out[20]: 
   AAA  BBB  CCC
0    4   10  100
1    5   20   50
2    6   30  -30
3    7   40  -50

In [21]: Crit1 = df.AAA <= 5.5

In [22]: Crit2 = df.BBB == 10.0

In [23]: Crit3 = df.CCC > -40.0

Можно использовать жёстко закодированные:

In [24]: AllCrit = Crit1 & Crit2 & Crit3

...Или это можно сделать с помощью списка динамически созданных критериев

In [25]: CritList = [Crit1,Crit2,Crit3]

In [26]: AllCrit = functools.reduce(lambda x,y: x & y, CritList)

In [27]: df[AllCrit]
Out[27]: 
   AAA  BBB  CCC
0    4   10  100

Выбор

DataFrames

Документация по индексации.

Использование меток строк и условий значений в булевой индексации

In [28]: df = pd.DataFrame(
   ....:      {'AAA' : [4,5,6,7], 'BBB' : [10,20,30,40],'CCC' : [100,50,-30,-50]}); df
   ....: 
Out[28]: 
   AAA  BBB  CCC
0    4   10  100
1    5   20   50
2    6   30  -30
3    7   40  -50

In [29]: df[(df.AAA <= 6) & (df.index.isin([0,2,4]))]
Out[29]: 
   AAA  BBB  CCC
0    4   10  100
2    6   30  -30

Использование loc для маркированного среза и iloc для позиционного среза

In [30]: data = {'AAA' : [4,5,6,7], 'BBB' : [10,20,30,40],'CCC' : [100,50,-30,-50]}

In [31]: df = pd.DataFrame(data=data,index=['foo','bar','boo','kar']); df
Out[31]: 
     AAA  BBB  CCC
foo    4   10  100
bar    5   20   50
boo    6   30  -30
kar    7   40  -50

Существует 2 явных метода среза, с третьим общим случаем

  1. Ориентированный на позиции (стиль среза Python: исключение конечного значения)
  2. Ориентированный на метки (не стиль среза Python: включение конечного значения)
  3. Общий (любой стиль среза: зависит от того, содержит ли срез метки или позиции)
In [32]: df.loc['bar':'kar'] #Label
Out[32]: 
     AAA  BBB  CCC
bar    5   20   50
boo    6   30  -30
kar    7   40  -50

#Generic
In [33]: df.ix[0:3] #Same as .iloc[0:3]
Out[33]: 
     AAA  BBB  CCC
foo    4   10  100
bar    5   20   50
boo    6   30  -30

In [34]: df.ix['bar':'kar'] #Same as .loc['bar':'kar']
Out[34]: 
     AAA  BBB  CCC
bar    5   20   50
boo    6   30  -30
kar    7   40  -50

Неясность возникает, когда индекс состоит из целых чисел с началом, отличным от нуля, или с шагом, отличным от единицы.

In [35]: df2 = pd.DataFrame(data=data,index=[1,2,3,4]); #Note index starts at 1.

In [36]: df2.iloc[1:3] #Position-oriented
Out[36]: 
   AAA  BBB  CCC
2    5   20   50
3    6   30  -30

In [37]: df2.loc[1:3] #Label-oriented
Out[37]: 
   AAA  BBB  CCC
1    4   10  100
2    5   20   50
3    6   30  -30

In [38]: df2.ix[1:3] #General, will mimic loc (label-oriented)
Out[38]: 
   AAA  BBB  CCC
1    4   10  100
2    5   20   50
3    6   30  -30

In [39]: df2.ix[0:3] #General, will mimic iloc (position-oriented), as loc[0:3] would raise a KeyError
Out[39]: 
   AAA  BBB  CCC
1    4   10  100
2    5   20   50
3    6   30  -30

Использование инверсного оператора (~) для взятия дополнения маски

In [40]: df = pd.DataFrame(
   ....:      {'AAA' : [4,5,6,7], 'BBB' : [10,20,30,40], 'CCC' : [100,50,-30,-50]}); df
   ....: 
Out[40]: 
   AAA  BBB  CCC
0    4   10  100
1    5   20   50
2    6   30  -30
3    7   40  -50

In [41]: df[~((df.AAA <= 6) & (df.index.isin([0,2,4])))]
Out[41]: 
   AAA  BBB  CCC
1    5   20   50
3    7   40  -50

Панели

Расширение таблицы-панели путём транспонирования, добавления новой размерности и обратного транспонирования до первоначальных размеров

In [42]: rng = pd.date_range('1/1/2013',periods=100,freq='D')

In [43]: data = np.random.randn(100, 4)

In [44]: cols = ['A','B','C','D']

In [45]: df1, df2, df3 = pd.DataFrame(data, rng, cols), pd.DataFrame(data, rng, cols), pd.DataFrame(data, rng, cols)

In [46]: pf = pd.Panel({'df1':df1,'df2':df2,'df3':df3});pf
Out[46]: 
<class 'pandas.core.panel.Panel'>
Dimensions: 3 (items) x 100 (major_axis) x 4 (minor_axis)
Items axis: df1 to df3
Major_axis axis: 2013-01-01 00:00:00 to 2013-04-10 00:00:00
Minor_axis axis: A to D

#Assignment using Transpose  (pandas < 0.15)
In [47]: pf = pf.transpose(2,0,1)

In [48]: pf['E'] = pd.DataFrame(data, rng, cols)

In [49]: pf = pf.transpose(1,2,0);pf
Out[49]: 
<class 'pandas.core.panel.Panel'>
Dimensions: 3 (items) x 100 (major_axis) x 5 (minor_axis)
Items axis: df1 to df3
Major_axis axis: 2013-01-01 00:00:00 to 2013-04-10 00:00:00
Minor_axis axis: A to E

#Direct assignment (pandas > 0.15)
In [50]: pf.loc[:,:,'F'] = pd.DataFrame(data, rng, cols);pf
Out[50]: 
<class 'pandas.core.panel.Panel'>
Dimensions: 3 (items) x 100 (major_axis) x 6 (minor_axis)
Items axis: df1 to df3
Major_axis axis: 2013-01-01 00:00:00 to 2013-04-10 00:00:00
Minor_axis axis: A to F

Маскирование панели с использованием np.where и последующее восстановление панели с новыми замаскированными значениями

Новые столбцы

Эффективное и динамическое создание новых столбцов с помощью applymap

In [51]: df = pd.DataFrame(
   ....:      {'AAA' : [1,2,1,3], 'BBB' : [1,1,2,2], 'CCC' : [2,1,3,1]}); df
   ....: 
Out[51]: 
   AAA  BBB  CCC
0    1    1    2
1    2    1    1
2    1    2    3
3    3    2    1

In [52]: source_cols = df.columns # or some subset would work too.

In [53]: new_cols = [str(x) + "_cat" for x in source_cols]

In [54]: categories = {1 : 'Alpha', 2 : 'Beta', 3 : 'Charlie' }

In [55]: df[new_cols] = df[source_cols].applymap(categories.get);df
Out[55]: 
   AAA  BBB  CCC  AAA_cat BBB_cat  CCC_cat
0    1    1    2    Alpha   Alpha     Beta
1    2    1    1     Beta   Alpha    Alpha
2    1    2    3    Alpha    Beta  Charlie
3    3    2    1  Charlie    Beta    Alpha

Сохранение других столбцов при использовании min() с groupby

In [56]: df = pd.DataFrame(
   ....:      {'AAA' : [1,1,1,2,2,2,3,3], 'BBB' : [2,1,3,4,5,1,2,3]}); df
   ....: 
Out[56]: 
   AAA  BBB
0    1    2
1    1    1
2    1    3
3    2    4
4    2    5
5    2    1
6    3    2
7    3    3

Метод 1: idxmin() для получения индекса минимумов

In [57]: df.loc[df.groupby("AAA")["BBB"].idxmin()]
Out[57]: 
   AAA  BBB
1    1    1
5    2    1
6    3    2

Метод 2: сортировка, затем взятие первого в каждом

In [58]: df.sort_values(by="BBB").groupby("AAA", as_index=False).first()
Out[58]: 
   AAA  BBB
0    1    1
1    2    1
2    3    2

Обратите внимание на одинаковые результаты, за исключением индекса.

Многоуровневые индексы

Документация по многоуровневым индексам.

Создание многоуровневого индекса из таблицы с метками

In [59]: df = pd.DataFrame({'row' : [0,1,2],
   ....:                    'One_X' : [1.1,1.1,1.1],
   ....:                    'One_Y' : [1.2,1.2,1.2],
   ....:                    'Two_X' : [1.11,1.11,1.11],
   ....:                    'Two_Y' : [1.22,1.22,1.22]}); df
   ....: 
Out[59]: 
   One_X  One_Y  Two_X  Two_Y  row
0    1.1    1.2   1.11   1.22    0
1    1.1    1.2   1.11   1.22    1
2    1.1    1.2   1.11   1.22    2

# As Labelled Index
In [60]: df = df.set_index('row');df
Out[60]: 
     One_X  One_Y  Two_X  Two_Y
row                            
0      1.1    1.2   1.11   1.22
1      1.1    1.2   1.11   1.22
2      1.1    1.2   1.11   1.22

# With Hierarchical Columns
In [61]: df.columns = pd.MultiIndex.from_tuples([tuple(c.split('_')) for c in df.columns]);df
Out[61]: 
     One        Two      
       X    Y     X     Y
row                      
0    1.1  1.2  1.11  1.22
1    1.1  1.2  1.11  1.22
2    1.1  1.2  1.11  1.22

# Now stack & Reset
In [62]: df = df.stack(0).reset_index(1);df
Out[62]: 
    level_1     X     Y
row                    
0       One  1.10  1.20
0       Two  1.11  1.22
1       One  1.10  1.20
1       Two  1.11  1.22
2       One  1.10  1.20
2       Two  1.11  1.22

# And fix the labels (Notice the label 'level_1' got added automatically)
In [63]: df.columns = ['Sample','All_X','All_Y'];df
Out[63]: 
    Sample  All_X  All_Y
row                     
0      One   1.10   1.20
0      Two   1.11   1.22
1      One   1.10   1.20
1      Two   1.11   1.22
2      One   1.10   1.20
2      Two   1.11   1.22

Арифметика

Выполнение арифметических операций с многоуровневым индексом, требующим трансляции

In [64]: cols = pd.MultiIndex.from_tuples([ (x,y) for x in ['A','B','C'] for y in ['O','I']])

In [65]: df = pd.DataFrame(np.random.randn(2,6),index=['n','m'],columns=cols); df
Out[65]: 
          A                   B                   C          
          O         I         O         I         O         I
n  1.920906 -0.388231 -2.314394  0.665508  0.402562  0.399555
m -1.765956  0.850423  0.388054  0.992312  0.744086 -0.739776

In [66]: df = df.div(df['C'],level=1); df
Out[66]: 
          A                   B              C     
          O         I         O         I    O    I
n  4.771702 -0.971660 -5.749162  1.665625  1.0  1.0
m -2.373321 -1.149568  0.521518 -1.341367  1.0  1.0

Срез

Срез многоуровневого индекса с помощью xs

In [67]: coords = [('AA','one'),('AA','six'),('BB','one'),('BB','two'),('BB','six')]

In [68]: index = pd.MultiIndex.from_tuples(coords)

In [69]: df = pd.DataFrame([11,22,33,44,55],index,['MyData']); df
Out[69]: 
        MyData
AA one      11
   six      22
BB one      33
   two      44
   six      55

Для взятия поперечного сечения первого уровня и первой оси индекса:

In [70]: df.xs('BB',level=0,axis=0)  #Note : level and axis are optional, and default to zero
Out[70]: 
     MyData
one      33
two      44
six      55

...и теперь второго уровня первой оси.

In [71]: df.xs('six',level=1,axis=0)
Out[71]: 
    MyData
AA      22
BB      55

Срез многоуровневого индекса с помощью xs, метод #2

In [72]: index = list(itertools.product(['Ada','Quinn','Violet'],['Comp','Math','Sci']))

In [73]: headr = list(itertools.product(['Exams','Labs'],['I','II']))

In [74]: indx = pd.MultiIndex.from_tuples(index,names=['Student','Course'])

In [75]: cols = pd.MultiIndex.from_tuples(headr) #Notice these are un-named

In [76]: data = [[70+x+y+(x*y)%3 for x in range(4)] for y in range(9)]

In [77]: df = pd.DataFrame(data,indx,cols); df
Out[77]: 
               Exams     Labs    
                   I  II    I  II
Student Course                   
Ada     Comp      70  71   72  73
        Math      71  73   75  74
        Sci       72  75   75  75
Quinn   Comp      73  74   75  76
        Math      74  76   78  77
        Sci       75  78   78  78
Violet  Comp      76  77   78  79
        Math      77  79   81  80
        Sci       78  81   81  81

In [78]: All = slice(None)

In [79]: df.loc['Violet']
Out[79]: 
       Exams     Labs    
           I  II    I  II
Course                   
Comp      76  77   78  79
Math      77  79   81  80
Sci       78  81   81  81

In [80]: df.loc[(All,'Math'),All]
Out[80]: 
               Exams     Labs    
                   I  II    I  II
Student Course                   
Ada     Math      71  73   75  74
Quinn   Math      74  76   78  77
Violet  Math      77  79   81  80

In [81]: df.loc[(slice('Ada','Quinn'),'Math'),All]
Out[81]: 
               Exams     Labs    
                   I  II    I  II
Student Course                   
Ada     Math      71  73   75  74
Quinn   Math      74  76   78  77

In [82]: df.loc[(All,'Math'),('Exams')]
Out[82]: 
                 I  II
Student Course        
Ada     Math    71  73
Quinn   Math    74  76
Violet  Math    77  79

In [83]: df.loc[(All,'Math'),(All,'II')]
Out[83]: 
               Exams Labs
                  II   II
Student Course           
Ada     Math      73   74
Quinn   Math      76   77
Violet  Math      79   80

Установка частей многоуровневого индекса с помощью xs

Сортировка

Сортировка по определённому столбцу или упорядоченному списку столбцов с многоуровневым индексом

In [84]: df.sort_values(by=('Labs', 'II'), ascending=False)
Out[84]: 
               Exams     Labs    
                   I  II    I  II
Student Course                   
Violet  Sci       78  81   81  81
        Math      77  79   81  80
        Comp      76  77   78  79
Quinn   Sci       75  78   78  78
        Math      74  76   78  77
        Comp      73  74   75  76
Ada     Sci       72  75   75  75
        Math      71  73   75  74
        Comp      70  71   72  73

Частичный выбор, необходимость упорядоченности

Уровни

Добавление уровня к многоуровневому индексу

Разворачивание иерархических столбцов

panelnd

Документация по panelnd.

Построение 5-мерной панели panelnd

Пропущенные данные

Документация по пропущенным данным.

Заполнение вперёд обратной временной последовательности

In [85]: df = pd.DataFrame(np.random.randn(6,1), index=pd.date_range('2013-08-01', periods=6, freq='B'), columns=list('A'))

In [86]: df.ix[3,'A'] = np.nan

In [87]: df
Out[87]: 
                   A
2013-08-01 -1.054874
2013-08-02 -0.179642
2013-08-05  0.639589
2013-08-06       NaN
2013-08-07  1.906684
2013-08-08  0.104050

In [88]: df.reindex(df.index[::-1]).ffill()
Out[88]: 
                   A
2013-08-08  0.104050
2013-08-07  1.906684
2013-08-06  1.906684
2013-08-05  0.639589
2013-08-02 -0.179642
2013-08-01 -1.054874

cumsum сброс при значениях NaN

Замена

Использование replace с обратными ссылками

Группировка

Документация по группировке.

Базовая группировка с apply

В отличие от agg, вызываемая функция apply получает подтаблицу, что даёт доступ ко всем столбцам

In [89]: df = pd.DataFrame({'animal': 'cat dog cat fish dog cat cat'.split(),
   ....:                    'size': list('SSMMMLL'),
   ....:                    'weight': [8, 10, 11, 1, 20, 12, 12],
   ....:                    'adult' : [False] * 5 + [True] * 2}); df
   ....: 
Out[89]: 
   adult animal size  weight
0  False    cat    S       8
1  False    dog    S      10
2  False    cat    M      11
3  False   fish    M       1
4  False    dog    M      20
5   True    cat    L      12
6   True    cat    L      12

#List the size of the animals with the highest weight.
In [90]: df.groupby('animal').apply(lambda subf: subf['size'][subf['weight'].idxmax()])
Out[90]: 
animal
cat     L
dog     M
fish    M
dtype: object

Использование get_group

In [91]: gb = df.groupby(['animal'])

In [92]: gb.get_group('cat')
Out[92]: 
   adult animal size  weight
0  False    cat    S       8
2  False    cat    M      11
5   True    cat    L      12
6   True    cat    L      12

Применение разных функций к различным элементам в группе

In [93]: def GrowUp(x):
   ....:    avg_weight =  sum(x[x['size'] == 'S'].weight * 1.5)
   ....:    avg_weight += sum(x[x['size'] == 'M'].weight * 1.25)
   ....:    avg_weight += sum(x[x['size'] == 'L'].weight)
   ....:    avg_weight /= len(x)
   ....:    return pd.Series(['L',avg_weight,True], index=['size', 'weight', 'adult'])
   ....: 

In [94]: expected_df = gb.apply(GrowUp)

In [95]: expected_df
Out[95]: 
       size   weight adult
animal                    
cat       L  12.4375  True
dog       L  20.0000  True
fish      L   1.2500  True

Расширенное применение

In [96]: S = pd.Series([i / 100.0 for i in range(1,11)])

In [97]: def CumRet(x,y):
   ....:    return x * (1 + y)
   ....: 

In [98]: def Red(x):
   ....:    return functools.reduce(CumRet,x,1.0)
   ....: 

In [99]: S.expanding().apply(Red)
Out[99]: 
0    1.010000
1    1.030200
2    1.061106
3    1.103550
4    1.158728
5    1.228251
6    1.314229
7    1.419367
8    1.547110
9    1.701821
dtype: float64

Замена некоторых значений средними значениями остальной группы

In [100]: df = pd.DataFrame({'A' : [1, 1, 2, 2], 'B' : [1, -1, 1, 2]})

In [101]: gb = df.groupby('A')

In [102]: def replace(g):
   .....:    mask = g < 0
   .....:    g.loc[mask] = g[~mask].mean()
   .....:    return g
   .....: 

In [103]: gb.transform(replace)
Out[103]: 
     B
0  1.0
1  1.0
2  1.0
3  2.0

Сортировка групп по агрегированным данным

In [104]: df = pd.DataFrame({'code': ['foo', 'bar', 'baz'] * 2,
   .....:                    'data': [0.16, -0.21, 0.33, 0.45, -0.59, 0.62],
   .....:                    'flag': [False, True] * 3})
   .....: 

In [105]: code_groups = df.groupby('code')

In [106]: agg_n_sort_order = code_groups[['data']].transform(sum).sort_values(by='data')

In [107]: sorted_df = df.ix[agg_n_sort_order.index]

In [108]: sorted_df
Out[108]: 
  code  data   flag
1  bar -0.21   True
4  bar -0.59  False
0  foo  0.16  False
3  foo  0.45   True
2  baz  0.33  False
5  baz  0.62   True

Создание нескольких агрегированных столбцов

In [109]: rng = pd.date_range(start="2014-10-07",periods=10,freq='2min')

In [110]: ts = pd.Series(data = list(range(10)), index = rng)

In [111]: def MyCust(x):
   .....:    if len(x) > 2:
   .....:       return x[1] * 1.234
   .....:    return pd.NaT
   .....: 

In [112]: mhc = {'Mean' : np.mean, 'Max' : np.max, 'Custom' : MyCust}

In [113]: ts.resample("5min").apply(mhc)
Out[113]: 
                     Max Custom  Mean
2014-10-07 00:00:00    2  1.234   1.0
2014-10-07 00:05:00    4    NaT   3.5
2014-10-07 00:10:00    7  7.404   6.0
2014-10-07 00:15:00    9    NaT   8.5

In [114]: ts
Out[114]: 
2014-10-07 00:00:00    0
2014-10-07 00:02:00    1
2014-10-07 00:04:00    2
2014-10-07 00:06:00    3
2014-10-07 00:08:00    4
2014-10-07 00:10:00    5
2014-10-07 00:12:00    6
2014-10-07 00:14:00    7
2014-10-07 00:16:00    8
2014-10-07 00:18:00    9
Freq: 2T, dtype: int64

Создание столбца со значениями подсчётов и повторное присваивание в таблицу

In [115]: df = pd.DataFrame({'Color': 'Red Red Red Blue'.split(),
   .....:                    'Value': [100, 150, 50, 50]}); df
   .....: 
Out[115]: 
  Color  Value
0   Red    100
1   Red    150
2   Red     50
3  Blue     50

In [116]: df['Counts'] = df.groupby(['Color']).transform(len)

In [117]: df
Out[117]: 
  Color  Value  Counts
0   Red    100       3
1   Red    150       3
2   Red     50       3
3  Blue     50       1

Сдвиг групп значений в столбце на основе индекса

In [118]: df = pd.DataFrame(
   .....:    {u'line_race': [10, 10, 8, 10, 10, 8],
   .....:     u'beyer': [99, 102, 103, 103, 88, 100]},
   .....:     index=[u'Last Gunfighter', u'Last Gunfighter', u'Last Gunfighter',
   .....:            u'Paynter', u'Paynter', u'Paynter']); df
   .....: 
Out[118]: 
                 beyer  line_race
Last Gunfighter     99         10
Last Gunfighter    102         10
Last Gunfighter    103          8
Paynter            103         10
Paynter             88         10
Paynter            100          8

In [119]: df['beyer_shifted'] = df.groupby(level=0)['beyer'].shift(1)

In [120]: df
Out[120]: 
                 beyer  line_race  beyer_shifted
Last Gunfighter     99         10            NaN
Last Gunfighter    102         10           99.0
Last Gunfighter    103          8          102.0
Paynter            103         10            NaN
Paynter             88         10          103.0
Paynter            100          8           88.0

Выбор строки с максимальным значением из каждой группы

In [121]: df = pd.DataFrame({'host':['other','other','that','this','this'],
   .....:                    'service':['mail','web','mail','mail','web'],
   .....:                    'no':[1, 2, 1, 2, 1]}).set_index(['host', 'service'])
   .....: 

In [122]: mask = df.groupby(level=0).agg('idxmax')

In [123]: df_count = df.loc[mask['no']].reset_index()

In [124]: df_count
Out[124]: 
    host service  no
0  other     web   2
1   that    mail   1
2   this    mail   2

Группировка подобно itertools.groupby в Python

In [125]: df = pd.DataFrame([0, 1, 0, 1, 1, 1, 0, 1, 1], columns=['A'])

In [126]: df.A.groupby((df.A != df.A.shift()).cumsum()).groups
Out[126]: {1: [0], 2: [1], 3: [2], 4: [3, 4, 5], 5: [6], 6: [7, 8]}

In [127]: df.A.groupby((df.A != df.A.shift()).cumsum()).cumsum()
Out[127]: 
0    0
1    1
2    0
3    1
4    2
5    3
6    0
7    1
8    2
Name: A, dtype: int64

Расширение данных

Выравнивание и преобразование к дате

Вычисления с окном скользящего среднего на основе значений, а не счётчиков

Скользящее среднее по временным интервалам

Разделение

Разделение таблицы

Создание списка таблиц, разделённых с помощью разделительной линии, основанной на логике, содержащейся в строках.

In [128]: df = pd.DataFrame(data={'Case' : ['A','A','A','B','A','A','B','A','A'],
   .....:                         'Data' : np.random.randn(9)})
   .....: 

In [129]: dfs = list(zip(*df.groupby((1*(df['Case']=='B')).cumsum().rolling(window=3,min_periods=1).median())))[-1]

In [130]: dfs[0]
Out[130]: 
  Case      Data
0    A  0.174068
1    A -0.439461
2    A -0.741343
3    B -0.079673

In [131]: dfs[1]
Out[131]: 
  Case      Data
4    A -0.922875
5    A  0.303638
6    B -0.917368

In [132]: dfs[2]
Out[132]: 
  Case      Data
7    A -1.624062
8    A -0.758514

Pivot

Документация по Pivot.

Частичные суммы и промежуточные итоги

In [133]: df = pd.DataFrame(data={'Province' : ['ON','QC','BC','AL','AL','MN','ON'],
   .....:                          'City' : ['Toronto','Montreal','Vancouver','Calgary','Edmonton','Winnipeg','Windsor'],
   .....:                          'Sales' : [13,6,16,8,4,3,1]})
   .....: 

In [134]: table = pd.pivot_table(df,values=['Sales'],index=['Province'],columns=['City'],aggfunc=np.sum,margins=True)

In [135]: table.stack('City')
Out[135]: 
                    Sales
Province City            
AL       All         12.0
         Calgary      8.0
         Edmonton     4.0
BC       All         16.0
         Vancouver   16.0
MN       All          3.0
         Winnipeg     3.0
...                   ...
All      Calgary      8.0
         Edmonton     4.0
         Montreal     6.0
         Toronto     13.0
         Vancouver   16.0
         Windsor      1.0
         Winnipeg     3.0

[20 rows x 1 columns]

Таблица частот как в plyr в R

In [136]: grades = [48,99,75,80,42,80,72,68,36,78]

In [137]: df = pd.DataFrame( {'ID': ["x%d" % r for r in range(10)],
   .....:                     'Gender' : ['F', 'M', 'F', 'M', 'F', 'M', 'F', 'M', 'M', 'M'],
   .....:                     'ExamYear': ['2007','2007','2007','2008','2008','2008','2008','2009','2009','2009'],
   .....:                     'Class': ['algebra', 'stats', 'bio', 'algebra', 'algebra', 'stats', 'stats', 'algebra', 'bio', 'bio'],
   .....:                     'Participated': ['yes','yes','yes','yes','no','yes','yes','yes','yes','yes'],
   .....:                     'Passed': ['yes' if x > 50 else 'no' for x in grades],
   .....:                     'Employed': [True,True,True,False,False,False,False,True,True,False],
   .....:                     'Grade': grades})
   .....: 

In [138]: df.groupby('ExamYear').agg({'Participated': lambda x: x.value_counts()['yes'],
   .....:                     'Passed': lambda x: sum(x == 'yes'),
   .....:                     'Employed' : lambda x : sum(x),
   .....:                     'Grade' : lambda x : sum(x) / len(x)})
   .....: 
Out[138]: 
          Grade  Employed  Participated  Passed
ExamYear                                       
2007         74         3             3       2
2008         68         0             3       3
2009         60         2             3       2

Применение

Применение с "скользящим окном" для организации - Преобразование вложенных списков в фрейм с многоуровневым индексом

In [139]: df = pd.DataFrame(data={'A' : [[2,4,8,16],[100,200],[10,20,30]], 'B' : [['a','b','c'],['jj','kk'],['ccc']]},index=['I','II','III'])

In [140]: def SeriesFromSubList(aList):
   .....:    return pd.Series(aList)
   .....: 

In [141]: df_orgz = pd.concat(dict([ (ind,row.apply(SeriesFromSubList)) for ind,row in df.iterrows() ]))

Применение с "скользящим окном" к фрейму данных, возвращающему ряд

Применение с "скользящим окном" к нескольким столбцам, где функция вычисляет ряд, а затем возвращает скаляр из ряда

In [142]: df = pd.DataFrame(data=np.random.randn(2000,2)/10000,
   .....:                   index=pd.date_range('2001-01-01',periods=2000),
   .....:                   columns=['A','B']); df
   .....: 
Out[142]: 
                   A         B
2001-01-01 -0.000056 -0.000059
2001-01-02 -0.000107 -0.000168
2001-01-03  0.000040  0.000061
2001-01-04  0.000039  0.000182
2001-01-05  0.000071 -0.000067
2001-01-06  0.000024  0.000031
2001-01-07  0.000012 -0.000021
...              ...       ...
2006-06-17  0.000129  0.000094
2006-06-18  0.000059  0.000216
2006-06-19 -0.000069  0.000283
2006-06-20  0.000089  0.000084
2006-06-21  0.000075  0.000041
2006-06-22 -0.000037 -0.000011
2006-06-23 -0.000070 -0.000048

[2000 rows x 2 columns]

In [143]: def gm(aDF,Const):
   .....:    v = ((((aDF.A+aDF.B)+1).cumprod())-1)*Const
   .....:    return (aDF.index[0],v.iloc[-1])
   .....: 

In [144]: S = pd.Series(dict([ gm(df.iloc[i:min(i+51,len(df)-1)],5) for i in range(len(df)-50) ])); S
Out[144]: 
2001-01-01   -0.003108
2001-01-02   -0.001787
2001-01-03    0.000204
2001-01-04   -0.000166
2001-01-05   -0.002148
2001-01-06   -0.001831
2001-01-07   -0.001663
                ...   
2006-04-28   -0.009152
2006-04-29   -0.006728
2006-04-30   -0.005840
2006-05-01   -0.003650
2006-05-02   -0.003801
2006-05-03   -0.004272
2006-05-04   -0.003839
dtype: float64

Применение с "скользящим окном" к фрейму данных, возвращающему скаляр

Применение с "скользящим окном" к нескольким столбцам, где функция возвращает скаляр (объёмно взвешенная средняя цена)

In [145]: rng = pd.date_range(start = '2014-01-01',periods = 100)

In [146]: df = pd.DataFrame({'Open' : np.random.randn(len(rng)),
   .....:                    'Close' : np.random.randn(len(rng)),
   .....:                    'Volume' : np.random.randint(100,2000,len(rng))}, index=rng); df
   .....: 
Out[146]: 
               Close      Open  Volume
2014-01-01  1.550590  0.458513    1371
2014-01-02 -0.818812 -0.508850    1433
2014-01-03  1.160619  0.257610     645
2014-01-04  0.081521 -1.773393     878
2014-01-05  1.083284 -0.560676    1143
2014-01-06 -0.518721  0.284174    1088
2014-01-07  0.140661  1.146889    1722
...              ...       ...     ...
2014-04-04  0.458193 -0.669474    1768
2014-04-05  0.108502 -1.616315     836
2014-04-06  1.418082 -1.294906     694
2014-04-07  0.486530  1.171647     796
2014-04-08  0.181885  0.501639     265
2014-04-09 -0.707238 -0.361868    1293
2014-04-10  1.211432  1.564429    1088

[100 rows x 3 columns]

In [147]: def vwap(bars): return ((bars.Close*bars.Volume).sum()/bars.Volume.sum())

In [148]: window = 5

In [149]: s = pd.concat([ (pd.Series(vwap(df.iloc[i:i+window]), index=[df.index[i+window]])) for i in range(len(df)-window) ]);

In [150]: s.round(2)
Out[150]: 
2014-01-06    0.55
2014-01-07    0.06
2014-01-08    0.32
2014-01-09    0.03
2014-01-10    0.08
2014-01-11   -0.50
2014-01-12   -0.26
              ... 
2014-04-04    0.36
2014-04-05    0.48
2014-04-06    0.54
2014-04-07    0.46
2014-04-08    0.45
2014-04-09    0.53
2014-04-10    0.15
dtype: float64

Временные ряды

Между временами

Использование индексатора между временами

Построение диапазона дат, исключающего выходные дни и включающего только определённые время

Векторизованный поиск

Агрегирование и построение временных рядов

Преобразование матрицы с часами в столбцах и днями в строках в непрерывную последовательность строк в виде временного ряда. Как переупорядочить фрейм данных Pandas?

Обработка дубликатов при повторном индексировании временного ряда с заданной частотой

Вычисление первого числа месяца для каждого элемента в DatetimeIndex

In [151]: dates = pd.date_range('2000-01-01', periods=5)

In [152]: dates.to_period(freq='M').to_timestamp()
Out[152]: 
DatetimeIndex(['2000-01-01', '2000-01-01', '2000-01-01', '2000-01-01',
               '2000-01-01'],
              dtype='datetime64[ns]', freq=None)

Перевыборка

Документация по Перевыборке.

Группировка значений по времени

Группировка по времени #2

Использование TimeGrouper и другой группировки для создания подгрупп, а затем применение пользовательской функции

Перевыборка с пользовательскими периодами

Перевыборка внутридневного фрейма без добавления новых дней

Перевыборка минутных данных

Перевыборка с группировкой

Объединение

Документация по Конкатенации. Документация по Объединению.

Добавление двух фреймов данных с перекрывающимся индексом (эмуляция R rbind)

In [153]: rng = pd.date_range('2000-01-01', periods=6)

In [154]: df1 = pd.DataFrame(np.random.randn(6, 3), index=rng, columns=['A', 'B', 'C'])

In [155]: df2 = df1.copy()

ignore_index необходим в pandas < v0.13 и в зависимости от построения фрейма

In [156]: df = df1.append(df2,ignore_index=True); df
Out[156]: 
           A         B         C
0  -0.174202 -0.477257  0.239870
1  -0.654455 -1.411456 -1.778457
2   0.351578  0.307871 -0.286865
3   0.565398 -0.185821  0.937593
4   0.446473  0.566368  0.721476
5   1.710685 -0.667054 -0.651191
6  -0.174202 -0.477257  0.239870
7  -0.654455 -1.411456 -1.778457
8   0.351578  0.307871 -0.286865
9   0.565398 -0.185821  0.937593
10  0.446473  0.566368  0.721476
11  1.710685 -0.667054 -0.651191

Самообъединение фрейма данных

In [157]: df = pd.DataFrame(data={'Area' : ['A'] * 5 + ['C'] * 2,
   .....:                         'Bins' : [110] * 2 + [160] * 3 + [40] * 2,
   .....:                         'Test_0' : [0, 1, 0, 1, 2, 0, 1],
   .....:                         'Data' : np.random.randn(7)});df
   .....: 
Out[157]: 
  Area  Bins      Data  Test_0
0    A   110 -0.399974       0
1    A   110 -1.519206       1
2    A   160  1.678487       0
3    A   160  0.005345       1
4    A   160 -0.534461       2
5    C    40  0.255077       0
6    C    40  1.093310       1

In [158]: df['Test_1'] = df['Test_0'] - 1

In [159]: pd.merge(df, df, left_on=['Bins', 'Area','Test_0'], right_on=['Bins', 'Area','Test_1'],suffixes=('_L','_R'))
Out[159]: 
  Area  Bins    Data_L  Test_0_L  Test_1_L    Data_R  Test_0_R  Test_1_R
0    A   110 -0.399974         0        -1 -1.519206         1         0
1    A   160  1.678487         0        -1  0.005345         1         0
2    A   160  0.005345         1         0 -0.534461         2         1
3    C    40  0.255077         0        -1  1.093310         1         0

Как установить индекс и выполнить объединение

Объединение "asof" по аналогии с KDB

Объединение по критериям, основанным на значениях

Использование searchsorted для объединения на основе значений в диапазоне

Построение графиков

Документация по Построению графиков.

Настройка Matplotlib по аналогии с R

Настройка основных и второстепенных меток и подписей оси X

Построение нескольких графиков в ячейке ipython notebook

Создание многострочного графика

Построение тепловой карты

Добавление аннотаций к графику временного ряда

Добавление аннотаций к графику временного ряда #2

Генерация встроенных графиков в файлах Excel с помощью Pandas, Vincent и xlsxwriter

Диаграмма размаха для каждого квартиля стратифицирующей переменной

In [160]: df = pd.DataFrame(
   .....:      {u'stratifying_var': np.random.uniform(0, 100, 20),
   .....:       u'price': np.random.normal(100, 5, 20)})
   .....: 

In [161]: df[u'quartiles'] = pd.qcut(
   .....:     df[u'stratifying_var'],
   .....:     4,
   .....:     labels=[u'0-25%', u'25-50%', u'50-75%', u'75-100%'])
   .....: 

In [162]: df.boxplot(column=u'price', by=u'quartiles')
Out[162]: <matplotlib.axes._subplots.AxesSubplot at 0x11d038150>
_images/quartile_boxplot.png

Данные Ввод/Вывод

Сравнение производительности SQL и HDF5

CSV

Документация по CSV

read_csv в действии

Добавление в CSV

Как читать несколько файлов, добавляя их в единую таблицу DataFrame

Чтение CSV по частям

Чтение только определенных строк CSV по частям

Чтение первых нескольких строк таблицы

Чтение файла, сжатого не с помощью gzip/bz2 (родные сжатые форматы, которые read_csv понимает). В этом примере показан файл WinZipped, но это общее применение открытия файла в контекстном менеджере и использования этого обработчика для чтения. См. здесь

Определение типов из файла

Обработка плохих строк

Обработка плохих строк II

Чтение CSV с Unix-временными метками и преобразование в локальное время

Запись CSV с многоуровневым индексом без дублирования строк

Анализ компонент даты в нескольких столбцах быстрее с помощью формата

In [30]: i = pd.date_range('20000101',periods=10000)

In [31]: df = pd.DataFrame(dict(year = i.year, month = i.month, day = i.day))

In [32]: df.head()
Out[32]:
   day  month  year
0    1      1  2000
1    2      1  2000
2    3      1  2000
3    4      1  2000
4    5      1  2000

In [33]: %timeit pd.to_datetime(df.year*10000+df.month*100+df.day,format='%Y%m%d')
100 loops, best of 3: 7.08 ms per loop

# simulate combinging into a string, then parsing
In [34]: ds = df.apply(lambda x: "%04d%02d%02d" % (x['year'],x['month'],x['day']),axis=1)

In [35]: ds.head()
Out[35]:
0    20000101
1    20000102
2    20000103
3    20000104
4    20000105
dtype: object

In [36]: %timeit pd.to_datetime(ds)
1 loops, best of 3: 488 ms per loop

Пропуск строки между заголовком и данными

In [163]: from io import StringIO

In [164]: import pandas as pd

In [165]: data = """;;;;
   .....:  ;;;;
   .....:  ;;;;
   .....:  ;;;;
   .....:  ;;;;
   .....:  ;;;;
   .....: ;;;;
   .....:  ;;;;
   .....:  ;;;;
   .....: ;;;;
   .....: date;Param1;Param2;Param4;Param5
   .....:     ;m²;°C;m²;m
   .....: ;;;;
   .....: 01.01.1990 00:00;1;1;2;3
   .....: 01.01.1990 01:00;5;3;4;5
   .....: 01.01.1990 02:00;9;5;6;7
   .....: 01.01.1990 03:00;13;7;8;9
   .....: 01.01.1990 04:00;17;9;10;11
   .....: 01.01.1990 05:00;21;11;12;13
   .....: """
   .....: 
Вариант 1: явное указание строк для пропуска
In [166]: pd.read_csv(StringIO(data.decode('UTF-8')), sep=';', skiprows=[11,12],
   .....:         index_col=0, parse_dates=True, header=10)
   .....: 
Out[166]: 
                     Param1  Param2  Param4  Param5
date                                               
1990-01-01 00:00:00       1       1       2       3
1990-01-01 01:00:00       5       3       4       5
1990-01-01 02:00:00       9       5       6       7
1990-01-01 03:00:00      13       7       8       9
1990-01-01 04:00:00      17       9      10      11
1990-01-01 05:00:00      21      11      12      13
Вариант 2: чтение названий столбцов, а затем данных
In [167]: pd.read_csv(StringIO(data.decode('UTF-8')), sep=';',
   .....:         header=10, parse_dates=True, nrows=10).columns
   .....: 
Out[167]: Index([u'date', u'Param1', u'Param2', u'Param4', u'Param5'], dtype='object')

In [168]: columns = pd.read_csv(StringIO(data.decode('UTF-8')), sep=';',
   .....:                   header=10, parse_dates=True, nrows=10).columns
   .....: 

In [169]: pd.read_csv(StringIO(data.decode('UTF-8')), sep=';',
   .....:             header=12, parse_dates=True, names=columns)
   .....: 
Out[169]: 
               date  Param1  Param2  Param4  Param5
0  01.01.1990 00:00       1       1       2       3
1  01.01.1990 01:00       5       3       4       5
2  01.01.1990 02:00       9       5       6       7
3  01.01.1990 03:00      13       7       8       9
4  01.01.1990 04:00      17       9      10      11
5  01.01.1990 05:00      21      11      12      13

SQL

См. SQL документацию

Чтение из баз данных с помощью SQL

Excel

См. Excel документацию

Чтение из объекта-файла

Изменение форматирования в выводе XlsxWriter

HTML

Чтение HTML-таблиц с сервера, который не обрабатывает заголовок запроса по умолчанию

HDFStore

Документация по HDFStores

Простые запросы со временным индексом

Управление разнородными данными с использованием связанной иерархии нескольких таблиц

Слияние таблиц на диске с миллионами строк

Избегание несоответствий при записи в хранилище из нескольких процессов/потоков

Удаление дубликатов из большого хранилища по частям, по сути, рекурсивная операция сокращения. Показана функция, которая принимает данные из файла csv и создает хранилище по частям, а также парсинг дат. См. здесь

Создание хранилища по частям из файла csv

Добавление в хранилище с созданием уникального индекса

Потоки обработки больших данных

Чтение последовательности файлов, затем предоставление глобального уникального индекса для хранилища при добавлении

Группировка в HDFStore с низкой плотностью групп

Группировка в HDFStore с высокой плотностью групп

Иерархические запросы в HDFStore

Подсчет с помощью HDFStore

Отладка исключений HDFStore

Установка min_itemsize для строк

Использование ptrepack для создания полностью отсортированного индекса в хранилище

Хранение атрибутов в узле группы

In [170]: df = pd.DataFrame(np.random.randn(8,3))

In [171]: store = pd.HDFStore('test.h5')

In [172]: store.put('df',df)

# you can store an arbitrary python object via pickle
In [173]: store.get_storer('df').attrs.my_attribute = dict(A = 10)

In [174]: store.get_storer('df').attrs.my_attribute
Out[174]: {'A': 10}

Файлы двоичных данных

pandas легко принимает массивы numpy record, если вам нужно прочитать двоичный файл, состоящий из массива C-структур. Например, данный C-программа в файле под названием main.c скомпилирована с gcc main.c -std=gnu99 на 64-битной машине,

#include <stdio.h>
#include <stdint.h>

typedef struct _Data
{
    int32_t count;
    double avg;
    float scale;
} Data;

int main(int argc, const char *argv[])
{
    size_t n = 10;
    Data d[n];

    for (int i = 0; i < n; ++i)
    {
        d[i].count = i;
        d[i].avg = i + 1.0;
        d[i].scale = (float) i + 2.0f;
    }

    FILE *file = fopen("binary.dat", "wb");
    fwrite(&d, sizeof(Data), n, file);
    fclose(file);

    return 0;
}

следующий Python-код прочитает двоичный файл 'binary.dat' в pandas DataFrame, где каждый элемент структуры соответствует столбцу в таблице:

names = 'count', 'avg', 'scale'

# note that the offsets are larger than the size of the type because of
# struct padding
offsets = 0, 8, 16
formats = 'i4', 'f8', 'f4'
dt = np.dtype({'names': names, 'offsets': offsets, 'formats': formats},
              align=True)
df = pd.DataFrame(np.fromfile('binary.dat', dt))

Примечание

Смещения элементов структуры могут отличаться в зависимости от архитектуры машины, на которой был создан файл. Использование формата двоичного файла без обработки для хранения данных не рекомендуется, поскольку он не является кроссплатформенным. Рекомендуется использовать HDF5 или msgpack, оба из которых поддерживаются средствами ввода/вывода pandas.

Вычисления

Численное интегрирование (на основе выборок) временного ряда

Timedeltas

Документация по Timedeltas.

Использование timedeltas

In [175]: s  = pd.Series(pd.date_range('2012-1-1', periods=3, freq='D'))

In [176]: s - s.max()
Out[176]: 
0   -2 days
1   -1 days
2    0 days
dtype: timedelta64[ns]

In [177]: s.max() - s
Out[177]: 
0   2 days
1   1 days
2   0 days
dtype: timedelta64[ns]

In [178]: s - datetime.datetime(2011,1,1,3,5)
Out[178]: 
0   364 days 20:55:00
1   365 days 20:55:00
2   366 days 20:55:00
dtype: timedelta64[ns]

In [179]: s + datetime.timedelta(minutes=5)
Out[179]: 
0   2012-01-01 00:05:00
1   2012-01-02 00:05:00
2   2012-01-03 00:05:00
dtype: datetime64[ns]

In [180]: datetime.datetime(2011,1,1,3,5) - s
Out[180]: 
0   -365 days +03:05:00
1   -366 days +03:05:00
2   -367 days +03:05:00
dtype: timedelta64[ns]

In [181]: datetime.timedelta(minutes=5) + s
Out[181]: 
0   2012-01-01 00:05:00
1   2012-01-02 00:05:00
2   2012-01-03 00:05:00
dtype: datetime64[ns]

Добавление и вычитание дельт и дат

In [182]: deltas = pd.Series([ datetime.timedelta(days=i) for i in range(3) ])

In [183]: df = pd.DataFrame(dict(A = s, B = deltas)); df
Out[183]: 
           A      B
0 2012-01-01 0 days
1 2012-01-02 1 days
2 2012-01-03 2 days

In [184]: df['New Dates'] = df['A'] + df['B'];

In [185]: df['Delta'] = df['A'] - df['New Dates']; df
Out[185]: 
           A      B  New Dates   Delta
0 2012-01-01 0 days 2012-01-01  0 days
1 2012-01-02 1 days 2012-01-03 -1 days
2 2012-01-03 2 days 2012-01-05 -2 days

In [186]: df.dtypes
Out[186]: 
A             datetime64[ns]
B            timedelta64[ns]
New Dates     datetime64[ns]
Delta        timedelta64[ns]
dtype: object

Еще один пример

Значения могут быть установлены как NaT с помощью np.nan, аналогично datetime

In [187]: y = s - s.shift(); y
Out[187]: 
0      NaT
1   1 days
2   1 days
dtype: timedelta64[ns]

In [188]: y[1] = np.nan; y
Out[188]: 
0      NaT
1      NaT
2   1 days
dtype: timedelta64[ns]

Псевдонимы имен осей

Для глобальной настройки псевдонимов имен осей можно определить эти две функции:

In [189]: def set_axis_alias(cls, axis, alias):
   .....:    if axis not in cls._AXIS_NUMBERS:
   .....:       raise Exception("invalid axis [%s] for alias [%s]" % (axis, alias))
   .....:    cls._AXIS_ALIASES[alias] = axis
   .....: 
In [190]: def clear_axis_alias(cls, axis, alias):
   .....:    if axis not in cls._AXIS_NUMBERS:
   .....:       raise Exception("invalid axis [%s] for alias [%s]" % (axis, alias))
   .....:    cls._AXIS_ALIASES.pop(alias,None)
   .....: 
In [191]: set_axis_alias(pd.DataFrame,'columns', 'myaxis2')

In [192]: df2 = pd.DataFrame(np.random.randn(3,2),columns=['c1','c2'],index=['i1','i2','i3'])

In [193]: df2.sum(axis='myaxis2')
Out[193]: 
i1    0.239786
i2    0.259018
i3    0.163470
dtype: float64

In [194]: clear_axis_alias(pd.DataFrame,'columns', 'myaxis2')

Создание примеров данных

Для создания фрейма данных из всех возможных комбинаций заданных значений, подобно функции R's expand.grid() , можно создать словарь, где ключи — имена столбцов, а значения — списки значений данных:

In [195]: def expand_grid(data_dict):
   .....:    rows = itertools.product(*data_dict.values())
   .....:    return pd.DataFrame.from_records(rows, columns=data_dict.keys())
   .....: 

In [196]: df = expand_grid(
   .....:    {'height': [60, 70],
   .....:     'weight': [100, 140, 180],
   .....:     'sex': ['Male', 'Female']})
   .....: 

In [197]: df
Out[197]: 
       sex  weight  height
0     Male     100      60
1     Male     100      70
2     Male     140      60
3     Male     140      70
4     Male     180      60
5     Male     180      70
6   Female     100      60
7   Female     100      70
8   Female     140      60
9   Female     140      70
10  Female     180      60
11  Female     180      70

© 2008–2012, AQR Capital Management, LLC, Lambda Foundry, Inc. and PyData Development Team
Licensed under the 3-clause BSD License.
https://pandas.pydata.org/pandas-docs/version/0.18.1/cookbook.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API