小秩学数据分析数据蛙数据分析每周作业

pandas0.24.x文档3.4 数据结构

2019-04-24  本文已影响4人  Lykit01

目录:
1 0.24.1版本新特性
2 安装
3马上开始
3.1 pandas概况
3.2 十分钟上手pandas
3.3 基础功能(一)
3.3 基础功能(二)
3.3基础功能(三)
3.4 数据结构

3.4 数据结构简介

我们先对pandas的基本数据结构进行一个简单快速的概览。数据类型、索引和轴标签/对齐等操作能对所有对象应用。首先,将NumPy和pandas引入你的命名空间。

In [1]: import numpy as np

In [2]: import pandas as pd

我们有个基本的信条:数据默认对齐。标签和数据间的联系不会被打破,除非你强制打破。
我们先简短地看看数据结构,然后考虑不同部分的函数和方法。

3.4.1 一维数据结构(Series)

Series是能处理任何数据类型(包括整数、字符串、浮点数和Python对象等等)的一维标签化数组。轴标签统称为索引。创建Series的基本方法是创建:

>>> s = pd.Series(data, index=index)

这里,传入的数据可以来自不同的类型:

从ndarray对象创建
如果原数据是ndarray,那么index必须和data的长度一样。如果没有传入索引值,将会创建一个包含[0,1,2,...,len(data)-1]的index。

In [3]: s = pd.Series(np.random.randn(5), index=['a', 'b', 'c', 'd', 'e'])

In [4]: s
Out[4]: 
a    0.469112
b   -0.282863
c   -1.509059
d   -1.135632
e    1.212112
dtype: float64

In [5]: s.index
Out[5]: Index(['a', 'b', 'c', 'd', 'e'], dtype='object')

In [6]: pd.Series(np.random.randn(5))
Out[6]: 
0   -0.173215
1    0.119209
2   -1.044236
3   -0.861849
4   -2.104569
dtype: float64

注意: pandas支持非唯一索引值。如果试图执行不支持重复索引值的操作,则此时将引发异常。懒惰的原因几乎都是基于性能的(在计算中有许多实例,比如GroupBy中不使用索引的部分)。
从dict对象创建
Series可以从dict实例化。

In [7]: d = {'b': 1, 'a': 0, 'c': 2}

In [8]: pd.Series(d)
Out[8]: 
b    1
a    0
c    2
dtype: int64

注意: 如果原数据是字典并且没有传入index,当你使用的Python版本大于等于3.6pandas版本大于等于0.23时,Series的索引将按照字典的插入顺序。
当你使用的Python版本小于3.6或者pandas版本小于0.23时,Series的索引将会是字典的键按照词序形成的列表。

在上面的例子中,如果你使用的Python版本比3.6低或者pandas版本比0.23低,Series,生成的Series是按照键的词序来排序的,即['a', 'b', 'c'],而不是['b', 'a', 'c']。如果传递了索引,则会匹配出与索引中的标签对应的数据中的值。

In [9]: d = {'a': 0., 'b': 1., 'c': 2.}

In [10]: pd.Series(d)
Out[10]: 
a    0.0
b    1.0
c    2.0
dtype: float64

In [11]: pd.Series(d, index=['b', 'c', 'd', 'a'])
Out[11]: 
b    1.0
c    2.0
d    NaN
a    0.0
dtype: float64

注意: NaN(not a number)是pandas使用的标准的缺失值处理器。

从标量值创建
如果原数据是标量值,必须提供一个索引。这个标量值会被重复来匹配index的长度。

In [12]: pd.Series(5., index=['a', 'b', 'c', 'd', 'e'])
Out[12]: 
a    5.0
b    5.0
c    5.0
d    5.0
e    5.0
dtype: float64
3.4.1.1 Series类似ndarray

Series表现地和ndarray非常像,并且是大多数NumPy函数的合法参数。然而,像切片这样的操作也会对索引进行切片。

In [13]: s[0]
Out[13]: 0.46911229990718628

In [14]: s[:3]
Out[14]: 
a    0.469112
b   -0.282863
c   -1.509059
dtype: float64

In [15]: s[s > s.median()]
Out[15]: 
a    0.469112
e    1.212112
dtype: float64

In [16]: s[[4, 3, 1]]
Out[16]: 
e    1.212112
d   -1.135632
b   -0.282863
dtype: float64

In [17]: np.exp(s)
Out[17]: 
a    1.598575
b    0.753623
c    0.221118
d    0.321219
e    3.360575
dtype: float64

注意:section部分,我们将要介绍基于数组的索引,比如s[[4,3,1]]。
和NumPy数组一样,一个Series也有dtype。

In [18]: s.dtype
Out[18]: dtype('float64')

float64是最常见的NumPy数据类型。不过,pandas和其他第三方库在一些地方扩展了NumPy的类型系统,在这些地方,dtype就是ExtensionDtype.在pandas一些例子中,数据类型是Categorical可为空的整数类型。详情请看dtypes.
如果你需要一个支持Series的数组,请使用Series.array.

In [19]: s.array
Out[19]: 
<PandasArray>
[ 0.46911229990718628, -0.28286334432866328,  -1.5090585031735124,
  -1.1356323710171934,   1.2121120250208506]
Length: 5, dtype: float64

如果你要做一些不需要索引的操作,直接访问数组更有用。(比如,禁用自动对齐
Series.array是扩展数组。简单来说,一个扩展数组只是包裹一个或多个具体的numpy.ndarray的容器。pandas知道怎样运用ExtensionArray并且将其储存在Series或DataFrame中的一列中。详情请看dtypes.Series只是类似ndarray,如果需要真正的ndarray,请使用Series.to_numpy().

In [20]: s.to_numpy()
Out[20]: array([ 0.4691, -0.2829, -1.5091, -1.1356,  1.2121])

即使Series由扩展数组支持,series.to_numpy()也将返回numpy ndarray。

3.4.1.2 Series类似字典

Series就像是一个大小灵活的字典,可以通过index标签取值和赋值:

In [21]: s['a']
Out[21]: 0.46911229990718628

In [22]: s['e'] = 12.

In [23]: s
Out[23]: 
a     0.469112
b    -0.282863
c    -1.509059
d    -1.135632
e    12.000000
dtype: float64

In [24]: 'e' in s
Out[24]: True

In [25]: 'f' in s
Out[25]: False

如果一个标签不存在,会抛出异常:

>>> s['f']
KeyError: 'f'

使用get方法,不存在的标签会返回None或者指定的默认值:

In [26]: s.get('f')

In [27]: s.get('f', np.nan)
Out[27]: nan

也可以参看属性访问部分.

3.4.1.3 矢量操作和Series的标签对齐

使用原始numpy数组时,通常不需要逐值循环。在pandas中对Series做同样的操作也是可行的。Series能够应用ndarray的大多数NumPy方法。

In [28]: s + s
Out[28]: 
a     0.938225
b    -0.565727
c    -3.018117
d    -2.271265
e    24.000000
dtype: float64

In [29]: s * 2
Out[29]: 
a     0.938225
b    -0.565727
c    -3.018117
d    -2.271265
e    24.000000
dtype: float64

In [30]: np.exp(s)
Out[30]: 
a         1.598575
b         0.753623
c         0.221118
d         0.321219
e    162754.791419
dtype: float64

np.exp()返回e的幂次方

Series和ndarray的关键不同点在于Series会根据标签自动对齐数据。因此,在写计算公式时不必考虑Series是否包含同样的标签。

In [31]: s[1:] + s[:-1]
Out[31]: 
a         NaN
b   -0.565727
c   -3.018117
d   -2.271265
e         NaN
dtype: float64

上面这个对于两个没有对齐的Series的操作的结果会产生一个对两者索引取并集的结果。如果一个标签在其中一个中找不到的话会被标注为NaN值。这样能够在不明确指定数据对齐的情况下,保证交互式的数据分析和研究更加自由灵活。pandas数据结构的集成的数据对齐特征使得pandas不同于大多数处理标签化数据的大多数相关工具。
注意: 通常,为了避免损失信息,我们选择让不同索引的对象之间的操作结果默认取并集。即使没有数据,索引标签也是计算中非常重要的信息。当然,你也可以通过dropna函数来把那些缺失值的标签也去掉。

3.4.1.4 name属性

Series有一个name属性。

In [32]: s = pd.Series(np.random.randn(5), name='something')

In [33]: s
Out[33]: 
0   -0.494929
1    1.071804
2    0.721555
3   -0.706771
4   -1.039575
Name: something, dtype: float64

In [34]: s.name
Out[34]: 'something'

在很多情况下,Series的name会自动指定,尤其是当你对DataFrame做1维切片时,下面你将会看到。
0.18.0版本的新特性
你能用pandas.Series.rename()方法对Series进行重命名。

In [35]: s2 = s.rename("different")

In [36]: s2.name
Out[36]: 'different'

注意这里的s和s2是不同的对象。

3.4.2 二维数据结构(DataFrame)

DataFrame 是2维的带标签的数据结构,它的列的数据类型可以不一样。你可以把它想象成一个电子表格、SQL表格或者由Series对象构成的字典。在pandas的对象当中,DataFrame是最常用的数据结构。和Series一样,DataFrame支持多种创建方式:

3.4.2.1 从Series或字典构成的字典创建

生成的index将是所有Series的index的并集。如果有任何嵌套的dict,这些dict将首先转换为Series。如果没有传入columns参数,列名将是排好序的字典key列表。

In [37]: d = {'one': pd.Series([1., 2., 3.], index=['a', 'b', 'c']),
   ....:      'two': pd.Series([1., 2., 3., 4.], index=['a', 'b', 'c', 'd'])}
   ....: 

In [38]: df = pd.DataFrame(d)

In [39]: df
Out[39]: 
   one  two
a  1.0  1.0
b  2.0  2.0
c  3.0  3.0
d  NaN  4.0

In [40]: pd.DataFrame(d, index=['d', 'b', 'a'])
Out[40]: 
   one  two
d  NaN  4.0
b  2.0  2.0
a  1.0  1.0

In [41]: pd.DataFrame(d, index=['d', 'b', 'a'], columns=['two', 'three'])
Out[41]: 
   two three
d  4.0   NaN
b  2.0   NaN
a  1.0   NaN

通过访问index和columns属性可以分别得到行和列标签。
注意: 从传入的字典创建DataFrame时,如果传入了columns参数,传入的columns参数将会覆盖掉字典本身的keys。

In [42]: df.index
Out[42]: Index(['a', 'b', 'c', 'd'], dtype='object')

In [43]: df.columns
Out[43]: Index(['one', 'two'], dtype='object')
3.4.2.2 从ndarray/列表构成的字典创建

一起传入的ndarray必须是同样长度的。如果要传入index参数,也必须和这些数组一样长。如果没有传入index参数,生成的index会是range(n),其中n是数组长度。

In [44]: d = {'one': [1., 2., 3., 4.],
   ....:      'two': [4., 3., 2., 1.]}
   ....: 

In [45]: pd.DataFrame(d)
Out[45]: 
   one  two
0  1.0  4.0
1  2.0  3.0
2  3.0  2.0
3  4.0  1.0

In [46]: pd.DataFrame(d, index=['a', 'b', 'c', 'd'])
Out[46]: 
   one  two
a  1.0  4.0
b  2.0  3.0
c  3.0  2.0
d  4.0  1.0
3.4.2.3 从结构化的或者record ndarray创建

这种情况的处理和上文对数组组成的字典的处理相同。

In [47]: data = np.zeros((2, ), dtype=[('A', 'i4'), ('B', 'f4'), ('C', 'a10')])

In [48]: data[:] = [(1, 2., 'Hello'), (2, 3., "World")]

In [49]: pd.DataFrame(data)
Out[49]: 
   A    B         C
0  1  2.0  b'Hello'
1  2  3.0  b'World'

In [50]: pd.DataFrame(data, index=['first', 'second'])
Out[50]: 
        A    B         C
first   1  2.0  b'Hello'
second  2  3.0  b'World'

In [51]: pd.DataFrame(data, columns=['C', 'A', 'B'])
Out[51]: 
          C  A    B
0  b'Hello'  1  2.0
1  b'World'  2  3.0

注意: DataFrame并不是完全像2维的NumPy ndarray那样工作的。

3.4.2.4 从字典构成的列表创建
In [52]: data2 = [{'a': 1, 'b': 2}, {'a': 5, 'b': 10, 'c': 20}]

In [53]: pd.DataFrame(data2)
Out[53]: 
   a   b     c
0  1   2   NaN
1  5  10  20.0

In [54]: pd.DataFrame(data2, index=['first', 'second'])
Out[54]: 
        a   b     c
first   1   2   NaN
second  5  10  20.0

In [55]: pd.DataFrame(data2, columns=['a', 'b'])
Out[55]: 
   a   b
0  1   2
1  5  10
3.4.2.5 从元组构成的字典创建

通过传入元组字典,你能自动创建一个多重索引的DataFrame。

In [56]: pd.DataFrame({('a', 'b'): {('A', 'B'): 1, ('A', 'C'): 2},
   ....:               ('a', 'a'): {('A', 'C'): 3, ('A', 'B'): 4},
   ....:               ('a', 'c'): {('A', 'B'): 5, ('A', 'C'): 6},
   ....:               ('b', 'a'): {('A', 'C'): 7, ('A', 'B'): 8},
   ....:               ('b', 'b'): {('A', 'D'): 9, ('A', 'B'): 10}})
   ....: 
Out[56]: 
       a              b      
       b    a    c    a     b
A B  1.0  4.0  5.0  8.0  10.0
  C  2.0  3.0  6.0  7.0   NaN
  D  NaN  NaN  NaN  NaN   9.0
3.4.2.6 来自Series

从Series创建DataFrame和Series有同样的index,列名也是来自Series,除非提供了其他列名。
缺失数据
详情请看缺失数据。在从含有缺失值的数据构建DataFrame时,我们用np.nan来代替那些缺失的数据。另外,你也可以传递一个numpy.MaskedArray参数给DataFrame构造器,其他覆盖的输入将会被认为是缺失值。

3.4.2.7 备选构造器

DataFrame.from_dict
DataFrame.from_dict接受字典或数组型的序列构成的字典,并且返回一个DataFrame。这个方法和DataFrame构造器很像,除了orient参数不一样,orient默认是'columns',但是也可以设置成'index',这样可以使用字典的keys作为行标签。

In [57]: pd.DataFrame.from_dict(dict([('A', [1, 2, 3]), ('B', [4, 5, 6])]))
Out[57]: 
   A  B
0  1  4
1  2  5
2  3  6

如果你传入orient='index',keys将会是行标签。在这种情况下,你可以传入想要的列名:

In [58]: pd.DataFrame.from_dict(dict([('A', [1, 2, 3]), ('B', [4, 5, 6])]),
   ....:                        orient='index', columns=['one', 'two', 'three'])
   ....: 
Out[58]: 
   one  two  three
A    1    2      3
B    4    5      6

DataFrame.from_records
DataFrame.from_records接受元组组成的列表或者结构化数据类型的ndarra.它和常规的DataFrame构造器类似,除了生成的DataFrame的索引可能是指定结构化数据类型的特定字段。比如:

In [59]: data
Out[59]: 
array([(1,  2., b'Hello'), (2,  3., b'World')],
      dtype=[('A', '<i4'), ('B', '<f4'), ('C', 'S10')])

In [60]: pd.DataFrame.from_records(data, index='C')
Out[60]: 
          A    B
C               
b'Hello'  1  2.0
b'World'  2  3.0
3.4.2.8 列选择、添加、删除

你可以从字面意思上把DataFrame看作是由类似索引的Series构成的字典。取值、赋值以及删除列都和对应的字典操作有相同的语法。

In [61]: df['one']
Out[61]: 
a    1.0
b    2.0
c    3.0
d    NaN
Name: one, dtype: float64

In [62]: df['three'] = df['one'] * df['two']

In [63]: df['flag'] = df['one'] > 2

In [64]: df
Out[64]: 
   one  two  three   flag
a  1.0  1.0    1.0  False
b  2.0  2.0    4.0  False
c  3.0  3.0    9.0   True
d  NaN  4.0    NaN  False

删除列也和字典相似。

In [65]: del df['two']

In [66]: three = df.pop('three')

In [67]: df
Out[67]: 
   one   flag
a  1.0  False
b  2.0  False
c  3.0   True
d  NaN  False

当插入一个标量值时,会自动推广到整个列。

In [68]: df['foo'] = 'bar'

In [69]: df
Out[69]: 
   one   flag  foo
a  1.0  False  bar
b  2.0  False  bar
c  3.0   True  bar
d  NaN  False  bar

当插入的Series和DataFrame的索引不同时,Series的索引将会被改造成DataFrame的索引。

In [70]: df['one_trunc'] = df['one'][:2]

In [71]: df
Out[71]: 
   one   flag  foo  one_trunc
a  1.0  False  bar        1.0
b  2.0  False  bar        2.0
c  3.0   True  bar        NaN
d  NaN  False  bar        NaN

你也可以插入原生的ndarray,但是长度必须和DataFrame的索引的长度相同。
默认情况下,插入的列会被放到最后面。但insert函数也支持在特定位置上进行插入。

In [72]: df.insert(1, 'bar', df['one'])

In [73]: df
Out[73]: 
   one  bar   flag  foo  one_trunc
a  1.0  1.0  False  bar        1.0
b  2.0  2.0  False  bar        2.0
c  3.0  3.0   True  bar        NaN
d  NaN  NaN  False  bar        NaN
3.4.2.9 在方法链中分配新列

dplyr的转换动词启发,DataFrame有一个assign()方法,允许用户创建可能来自已有的列的新列。

In [74]: iris = pd.read_csv('data/iris.data')

In [75]: iris.head()
Out[75]: 
   SepalLength  SepalWidth  PetalLength  PetalWidth         Name
0          5.1         3.5          1.4         0.2  Iris-setosa
1          4.9         3.0          1.4         0.2  Iris-setosa
2          4.7         3.2          1.3         0.2  Iris-setosa
3          4.6         3.1          1.5         0.2  Iris-setosa
4          5.0         3.6          1.4         0.2  Iris-setosa

In [76]: (iris.assign(sepal_ratio=iris['SepalWidth'] / iris['SepalLength'])
   ....:      .head())
   ....: 
Out[76]: 
   SepalLength  SepalWidth  PetalLength  PetalWidth         Name  sepal_ratio
0          5.1         3.5          1.4         0.2  Iris-setosa     0.686275
1          4.9         3.0          1.4         0.2  Iris-setosa     0.612245
2          4.7         3.2          1.3         0.2  Iris-setosa     0.680851
3          4.6         3.1          1.5         0.2  Iris-setosa     0.673913
4          5.0         3.6          1.4         0.2  Iris-setosa     0.720000

在上面的例子中,我们插入了一个预先计算的值。我们还可以传入一个参数的函数,它将在分配给的DataFrame上进行计算。

In [77]: iris.assign(sepal_ratio=lambda x: (x['SepalWidth'] / x['SepalLength'])).head()
Out[77]: 
   SepalLength  SepalWidth  PetalLength  PetalWidth         Name  sepal_ratio
0          5.1         3.5          1.4         0.2  Iris-setosa     0.686275
1          4.9         3.0          1.4         0.2  Iris-setosa     0.612245
2          4.7         3.2          1.3         0.2  Iris-setosa     0.680851
3          4.6         3.1          1.5         0.2  Iris-setosa     0.673913
4          5.0         3.6          1.4         0.2  Iris-setosa     0.720000

assign函数总是返回原数据的副本,而不改动原数据。
当你手头上没有DataFrame的引用时,传递可调用的而不是要插入的实际值非常有用。在做链式操作时非常常用。比如,我们在DataFrame中筛选出'SepalLength'列大于5的数据,计数比率,并作图。

In [78]: (iris.query('SepalLength > 5')
   ....:      .assign(SepalRatio=lambda x: x.SepalWidth / x.SepalLength,
   ....:              PetalRatio=lambda x: x.PetalWidth / x.PetalLength)
   ....:      .plot(kind='scatter', x='SepalRatio', y='PetalRatio'))
   ....: 
Out[78]: <matplotlib.axes._subplots.AxesSubplot at 0x7f2b527b1a58>

[图片上传失败...(image-b7a179-1556113063245)]
这里传递了一个函数,函数会在指派的DataFrame上计算。而且,DataFrame过滤出了'SepalLength'列大于5的行。先做了过滤,然后做了计算。这个例子中我们没有可用的过滤了的DataFrame可用。用于赋值的函数签名只是**Kwargs.键是新字段的列名,这些值要么是要插入的值(例如,一个序列或numpy数组),要么是要在DataFrame上调用的一个参数的函数。 函数会返回原数据的副本,同时插入了新值。
0.23.0版本新变化
使用Python3.6时,**kwargs的顺序会保留。这就支持了依赖赋值,即assign方法中的表达式的后面部分能引用前面部分新生成的参数。

In [79]: dfa = pd.DataFrame({"A": [1, 2, 3],
   ....:                     "B": [4, 5, 6]})
   ....: 

In [80]: dfa.assign(C=lambda x: x['A'] + x['B'],
   ....:            D=lambda x: x['A'] + x['C'])
   ....: 
Out[80]: 
   A  B  C   D
0  1  4  5   6
1  2  5  7   9
2  3  6  9  12

在同一个表达式中,x['C']代表了新生成的列,这等价于dfa['A']+dfa['B'].
为了使代码兼容所有版本的python,请把赋值表达式分成两部分:

In [81]: dependent = pd.DataFrame({"A": [1, 1, 1]})

In [82]: (dependent.assign(A=lambda x: x['A'] + 1)
   ....:           .assign(B=lambda x: x['A'] + 2))
   ....: 
Out[82]: 
   A  B
0  2  4
1  2  4
2  2  4

警告: 依赖赋值可能会在python 3.6和旧版本的python之间微妙地改变代码的行为。
如果你需要写同时支持3.6版本之前或之后的Python,在传入赋值表达式时请小心:

>>> dependent = pd.DataFrame({"A": [1, 1, 1]})
>>> dependent.assign(A=lambda x: x["A"] + 1, B=lambda x: x["A"] + 2)

对于Python3.5或者更早的版本,创建B列的表达式会引用到A列的“旧”值,结果是这样的:

   A  B
0  2  3
1  2  3
2  2  3

而对于Python3.6版本或之后的版本,创建B列的表达式会引用到A列的“新”值,结果是这样的:

   A  B
0  2  4
1  2  4
2  2  4
3.4.2.10 索引/选择

基本的索引方法如下:

操作 语法 结果
选择列 df[col] Series
通过标签选择行 df.loc[label] Series
通过整数位置来选取行 df.iloc[loc] Series
行切片 df[5:10] DataFrame
通过布尔向量选择行 df[bool_vec] DataFrame

举个例子,选取一行时,返回一个Series,其索引是DataFrame的列。

In [83]: df.loc['b']
Out[83]: 
one              2
bar              2
flag         False
foo            bar
one_trunc        2
Name: b, dtype: object

In [84]: df.iloc[2]
Out[84]: 
one             3
bar             3
flag         True
foo           bar
one_trunc     NaN
Name: c, dtype: object

有关复杂的基于标签的索引和切片的更详尽的处理,请参阅索引部分。在重新索引部分 ,我们会强调重新索引和转换到新标签集的基础。

3.4.2.11 数据对齐和运算

DataFrame之间的运算会自动对齐列和索引(行标签)。另外,生成的对象将会有所有DataFrame列和行标签的合集。

In [85]: df = pd.DataFrame(np.random.randn(10, 4), columns=['A', 'B', 'C', 'D'])

In [86]: df2 = pd.DataFrame(np.random.randn(7, 3), columns=['A', 'B', 'C'])

In [87]: df + df2
Out[87]: 
          A         B         C   D
0  0.045691 -0.014138  1.380871 NaN
1 -0.955398 -1.501007  0.037181 NaN
2 -0.662690  1.534833 -0.859691 NaN
3 -2.452949  1.237274 -0.133712 NaN
4  1.414490  1.951676 -2.320422 NaN
5 -0.494922 -1.649727 -1.084601 NaN
6 -1.047551 -0.748572 -0.805479 NaN
7       NaN       NaN       NaN NaN
8       NaN       NaN       NaN NaN
9       NaN       NaN       NaN NaN

对DataFrame和Series进行操作时,默认的操作是将Series的索引和DataFrame的列对齐,然后逐行推广。比如:

In [88]: df - df.iloc[0]
Out[88]: 
          A         B         C         D
0  0.000000  0.000000  0.000000  0.000000
1 -1.359261 -0.248717 -0.453372 -1.754659
2  0.253128  0.829678  0.010026 -1.991234
3 -1.311128  0.054325 -1.724913 -1.620544
4  0.573025  1.500742 -0.676070  1.367331
5 -1.741248  0.781993 -1.241620 -2.053136
6 -1.240774 -0.869551 -0.153282  0.000430
7 -0.743894  0.411013 -0.929563 -0.282386
8 -1.194921  1.320690  0.238224 -1.482644
9  2.293786  1.856228  0.773289 -1.446531

这里df.iloc[0]取的是第0行,上面的运算是逐行减去第0行

在处理时间序列的特殊情况下,并且DataFrame也包含日期,推广方向将是列维度的。

In [89]: index = pd.date_range('1/1/2000', periods=8)

In [90]: df = pd.DataFrame(np.random.randn(8, 3), index=index, columns=list('ABC'))

In [91]: df
Out[91]: 
                   A         B         C
2000-01-01 -1.226825  0.769804 -1.281247
2000-01-02 -0.727707 -0.121306 -0.097883
2000-01-03  0.695775  0.341734  0.959726
2000-01-04 -1.110336 -0.619976  0.149748
2000-01-05 -0.732339  0.687738  0.176444
2000-01-06  0.403310 -0.154951  0.301624
2000-01-07 -2.179861 -1.369849 -0.954208
2000-01-08  1.462696 -1.743161 -0.826591

In [92]: type(df['A'])
Out[92]: pandas.core.series.Series

In [93]: df - df['A']
Out[93]: 
            2000-01-01 00:00:00  2000-01-02 00:00:00  2000-01-03 00:00:00  2000-01-04 00:00:00  2000-01-05 00:00:00  ...  2000-01-07 00:00:00  2000-01-08 00:00:00   A   B   C
2000-01-01                  NaN                  NaN                  NaN                  NaN                  NaN  ...                  NaN                  NaN NaN NaN NaN
2000-01-02                  NaN                  NaN                  NaN                  NaN                  NaN  ...                  NaN                  NaN NaN NaN NaN
2000-01-03                  NaN                  NaN                  NaN                  NaN                  NaN  ...                  NaN                  NaN NaN NaN NaN
2000-01-04                  NaN                  NaN                  NaN                  NaN                  NaN  ...                  NaN                  NaN NaN NaN NaN
2000-01-05                  NaN                  NaN                  NaN                  NaN                  NaN  ...                  NaN                  NaN NaN NaN NaN
2000-01-06                  NaN                  NaN                  NaN                  NaN                  NaN  ...                  NaN                  NaN NaN NaN NaN
2000-01-07                  NaN                  NaN                  NaN                  NaN                  NaN  ...                  NaN                  NaN NaN NaN NaN
2000-01-08                  NaN                  NaN                  NaN                  NaN                  NaN  ...                  NaN                  NaN NaN NaN NaN

[8 rows x 11 columns]

警告:
df-df['A']已经弃用了,并且在未来的发行版中将被移除。完成这项操作更好的方式是:
df.sub(df['A'],axis=0)
如果想对匹配和推广有更精确的控制,请看二元操作部分.
对标量的操作和期望的一样:

In [94]: df * 5 + 2
Out[94]: 
                   A         B         C
2000-01-01 -4.134126  5.849018 -4.406237
2000-01-02 -1.638535  1.393469  1.510587
2000-01-03  5.478873  3.708672  6.798628
2000-01-04 -3.551681 -1.099880  2.748742
2000-01-05 -1.661697  5.438692  2.882222
2000-01-06  4.016548  1.225246  3.508122
2000-01-07 -8.899303 -4.849247 -2.771039
2000-01-08  9.313480 -6.715805 -2.132955

In [95]: 1 / df
Out[95]: 
                   A         B          C
2000-01-01 -0.815112  1.299033  -0.780489
2000-01-02 -1.374179 -8.243600 -10.216313
2000-01-03  1.437247  2.926250   1.041965
2000-01-04 -0.900628 -1.612966   6.677871
2000-01-05 -1.365487  1.454041   5.667510
2000-01-06  2.479485 -6.453662   3.315381
2000-01-07 -0.458745 -0.730007  -1.047990
2000-01-08  0.683669 -0.573671  -1.209788

In [96]: df ** 4
Out[96]: 
                    A         B         C
2000-01-01   2.265327  0.351172  2.694833
2000-01-02   0.280431  0.000217  0.000092
2000-01-03   0.234355  0.013638  0.848376
2000-01-04   1.519910  0.147740  0.000503
2000-01-05   0.287640  0.223714  0.000969
2000-01-06   0.026458  0.000576  0.008277
2000-01-07  22.579530  3.521204  0.829033
2000-01-08   4.577374  9.233151  0.466834

这也同样适用于布尔操作。

In [97]: df1 = pd.DataFrame({'a': [1, 0, 1], 'b': [0, 1, 1]}, dtype=bool)

In [98]: df2 = pd.DataFrame({'a': [0, 1, 1], 'b': [1, 1, 0]}, dtype=bool)

In [99]: df1 & df2
Out[99]: 
       a      b
0  False  False
1  False   True
2   True  False

In [100]: df1 | df2
Out[100]: 
      a     b
0  True  True
1  True  True
2  True  True

In [101]: df1 ^ df2
Out[101]: 
       a      b
0   True   True
1   True  False
2  False   True

In [102]: -df1
Out[102]: 
       a      b
0  False   True
1   True  False
2  False  False
3.4.2.12 转置

和ndarray类似,转置需要通过T属性。

# only show the first 5 rows
In [103]: df[:5].T
Out[103]: 
   2000-01-01  2000-01-02  2000-01-03  2000-01-04  2000-01-05
A   -1.226825   -0.727707    0.695775   -1.110336   -0.732339
B    0.769804   -0.121306    0.341734   -0.619976    0.687738
C   -1.281247   -0.097883    0.959726    0.149748    0.176444
3.4.2.13 DataFrame与NumPy函数的互操作性

假定DataFrame的数据是数值型的话,元素级别的NumPy函数(比如log,exp,sqrt等等)和其他的NumPy函数都可以没有问题地运行在DataFrame上。

In [104]: np.exp(df)
Out[104]: 
                   A         B         C
2000-01-01  0.293222  2.159342  0.277691
2000-01-02  0.483015  0.885763  0.906755
2000-01-03  2.005262  1.407386  2.610980
2000-01-04  0.329448  0.537957  1.161542
2000-01-05  0.480783  1.989212  1.192968
2000-01-06  1.496770  0.856457  1.352053
2000-01-07  0.113057  0.254145  0.385117
2000-01-08  4.317584  0.174966  0.437538

In [105]: np.asarray(df)
Out[105]: 
array([[-1.2268,  0.7698, -1.2812],
       [-0.7277, -0.1213, -0.0979],
       [ 0.6958,  0.3417,  0.9597],
       [-1.1103, -0.62  ,  0.1497],
       [-0.7323,  0.6877,  0.1764],
       [ 0.4033, -0.155 ,  0.3016],
       [-2.1799, -1.3698, -0.9542],
       [ 1.4627, -1.7432, -0.8266]])

DataFrame的dot方法可以进行矩阵乘法:

In [106]: df.T.dot(df)
Out[106]: 
           A         B         C
A  11.341858 -0.059772  3.007998
B  -0.059772  6.520556  2.083308
C   3.007998  2.083308  4.310549

类似的,Series的dot方法可以进行点积运算:

In [107]: s1 = pd.Series(np.arange(5, 10))

In [108]: s1.dot(s1)
Out[108]: 255

DataFrame并不是用来代替ndarray的,因为它的索引语义在某些地方与矩阵有很大的不同。

3.4.2.14 控制台展示

非常大的DataFrame会被截断成几部分,以便于在控制台中展示。运用info()方法可以得知其概况。(这里我从plyr R包读取了csv版本的baseball数据集。)

In [109]: baseball = pd.read_csv('data/baseball.csv')

In [110]: print(baseball)
       id     player  year  stint team  lg   g   ab   r    h  X2b  X3b  hr   rbi   sb   cs  bb    so  ibb  hbp   sh   sf  gidp
0   88641  womacto01  2006      2  CHN  NL  19   50   6   14    1    0   1   2.0  1.0  1.0   4   4.0  0.0  0.0  3.0  0.0   0.0
1   88643  schilcu01  2006      1  BOS  AL  31    2   0    1    0    0   0   0.0  0.0  0.0   0   1.0  0.0  0.0  0.0  0.0   0.0
..    ...        ...   ...    ...  ...  ..  ..  ...  ..  ...  ...  ...  ..   ...  ...  ...  ..   ...  ...  ...  ...  ...   ...
98  89533   aloumo01  2007      1  NYN  NL  87  328  51  112   19    1  13  49.0  3.0  0.0  27  30.0  5.0  2.0  0.0  3.0  13.0
99  89534  alomasa02  2007      1  NYN  NL   8   22   1    3    1    0   0   0.0  0.0  0.0   0   3.0  0.0  0.0  0.0  0.0   0.0

[100 rows x 23 columns]

In [111]: baseball.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 100 entries, 0 to 99
Data columns (total 23 columns):
id        100 non-null int64
player    100 non-null object
year      100 non-null int64
stint     100 non-null int64
team      100 non-null object
lg        100 non-null object
g         100 non-null int64
ab        100 non-null int64
r         100 non-null int64
h         100 non-null int64
X2b       100 non-null int64
X3b       100 non-null int64
hr        100 non-null int64
rbi       100 non-null float64
sb        100 non-null float64
cs        100 non-null float64
bb        100 non-null int64
so        100 non-null float64
ibb       100 non-null float64
hbp       100 non-null float64
sh        100 non-null float64
sf        100 non-null float64
gidp      100 non-null float64
dtypes: float64(9), int64(11), object(3)
memory usage: 18.0+ KB

不过,使用to_string()方法会用表格的方式呈现DataFrame,虽然有时不能很好地适应控制台:

In [112]: print(baseball.iloc[-20:, :12].to_string())
       id     player  year  stint team  lg    g   ab   r    h  X2b  X3b
80  89474  finlest01  2007      1  COL  NL   43   94   9   17    3    0
81  89480  embreal01  2007      1  OAK  AL    4    0   0    0    0    0
82  89481  edmonji01  2007      1  SLN  NL  117  365  39   92   15    2
83  89482  easleda01  2007      1  NYN  NL   76  193  24   54    6    0
84  89489  delgaca01  2007      1  NYN  NL  139  538  71  139   30    0
85  89493  cormirh01  2007      1  CIN  NL    6    0   0    0    0    0
86  89494  coninje01  2007      2  NYN  NL   21   41   2    8    2    0
87  89495  coninje01  2007      1  CIN  NL   80  215  23   57   11    1
88  89497  clemero02  2007      1  NYA  AL    2    2   0    1    0    0
89  89498  claytro01  2007      2  BOS  AL    8    6   1    0    0    0
90  89499  claytro01  2007      1  TOR  AL   69  189  23   48   14    0
91  89501  cirilje01  2007      2  ARI  NL   28   40   6    8    4    0
92  89502  cirilje01  2007      1  MIN  AL   50  153  18   40    9    2
93  89521  bondsba01  2007      1  SFN  NL  126  340  75   94   14    0
94  89523  biggicr01  2007      1  HOU  NL  141  517  68  130   31    3
95  89525  benitar01  2007      2  FLO  NL   34    0   0    0    0    0
96  89526  benitar01  2007      1  SFN  NL   19    0   0    0    0    0
97  89530  ausmubr01  2007      1  HOU  NL  117  349  38   82   16    3
98  89533   aloumo01  2007      1  NYN  NL   87  328  51  112   19    1
99  89534  alomasa02  2007      1  NYN  NL    8   22   1    3    1    0

默认情况下,宽的DataFrame会跨多行打印:

In [113]: pd.DataFrame(np.random.randn(3, 12))
Out[113]: 
         0         1         2         3         4         5         6         7         8         9         10        11
0 -0.345352  1.314232  0.690579  0.995761  2.396780  0.014871  3.357427 -0.317441 -1.236269  0.896171 -0.487602 -0.082240
1 -2.182937  0.380396  0.084844  0.432390  1.519970 -0.493662  0.600178  0.274230  0.132885 -0.023688  2.410179  1.450520
2  0.206053 -0.251905 -2.213588  1.063327  1.266143  0.299368 -0.863838  0.408204 -1.048089 -0.025747 -0.988387  0.094055

通过设置display.width参数可以改变每行的打印量:

In [114]: pd.set_option('display.width', 40)  # default is 80

In [115]: pd.DataFrame(np.random.randn(3, 12))
Out[115]: 
         0         1         2         3         4         5         6         7         8         9         10        11
0  1.262731  1.289997  0.082423 -0.055758  0.536580 -0.489682  0.369374 -0.034571 -2.484478 -0.281461  0.030711  0.109121
1  1.126203 -0.977349  1.474071 -0.064034 -1.282782  0.781836 -1.071357  0.441153  2.353925  0.583787  0.221471 -0.744471
2  0.758527  1.729689 -0.964980 -0.845696 -1.340896  1.846883 -1.328865  1.682706 -1.717693  0.888782  0.228440  0.901805

官网的展示是用拖动条的,因此一行可以展示完。现在的jupyternotebook也支持一行展示。

你也可以通过设置display.max_colwidth参数来调节单列的最大宽度。

In [116]: datafile = {'filename': ['filename_01', 'filename_02'],
   .....:             'path': ["media/user_name/storage/folder_01/filename_01",
   .....:                      "media/user_name/storage/folder_02/filename_02"]}
   .....: 

In [117]: pd.set_option('display.max_colwidth', 30)

In [118]: pd.DataFrame(datafile)
Out[118]: 
      filename                           path
0  filename_01  media/user_name/storage/fo...
1  filename_02  media/user_name/storage/fo...

In [119]: pd.set_option('display.max_colwidth', 100)

In [120]: pd.DataFrame(datafile)
Out[120]: 
      filename                                           path
0  filename_01  media/user_name/storage/folder_01/filename_01
1  filename_02  media/user_name/storage/folder_02/filename_02

你也可以通过expand_frame_repr可选项来关掉这个特性。这会在一格中打印整张表格。

3.4.2.15 DataFrame列属性访问和IPython自动补全

如果DataFrame的列标签是合法的Python变量名,这列可以通过属性的访问方法访问到。

In [121]: df = pd.DataFrame({'foo1': np.random.randn(5),
   .....:                    'foo2': np.random.randn(5)})
   .....: 

In [122]: df
Out[122]: 
       foo1      foo2
0  1.171216 -0.858447
1  0.520260  0.306996
2 -1.197071 -0.028665
3 -1.066969  0.384316
4 -0.303421  1.574159

In [123]: df.foo1
Out[123]: 
0    1.171216
1    0.520260
2   -1.197071
3   -1.066969
4   -0.303421
Name: foo1, dtype: float64

各列都和IPython的补全机制做了关联,因此可以通过tab键补全:

In [5]: df.fo<TAB>  # noqa: E225, E999
df.foo1  df.foo2

3.4.3 三维数据结构/面板(Panel)

警告: 在0.20.0版本,Panel被弃用了,并且在未来的版本中将被起用。请看弃用Panel部分.

Panel虽然使用地较少,但也是很重要的3维数据容器。“Panel data”这个术语来源于计量经济学,部分原因也是来自pandas这个名字:pan(el)-da(ta)-s. Panel3个轴的名字是为了在语义上更好地描述panel数据,尤其是其计量分析。不过,为了严格地对DataFrame对象进行切片和切分,你可能会发现轴名称有点随意。

3.4.3.1 从3维ndarray创建,可选轴标签参数
In [124]: wp = pd.Panel(np.random.randn(2, 5, 4), items=['Item1', 'Item2'],
   .....:               major_axis=pd.date_range('1/1/2000', periods=5),
   .....:               minor_axis=['A', 'B', 'C', 'D'])
   .....: 

In [125]: wp
Out[125]: 
<class 'pandas.core.panel.Panel'>
Dimensions: 2 (items) x 5 (major_axis) x 4 (minor_axis)
Items axis: Item1 to Item2
Major_axis axis: 2000-01-01 00:00:00 to 2000-01-05 00:00:00
Minor_axis axis: A to D
3.4.3.2 从DataFrame构成的字典创建
In [126]: data = {'Item1': pd.DataFrame(np.random.randn(4, 3)),
   .....:         'Item2': pd.DataFrame(np.random.randn(4, 2))}
   .....: 

In [127]: pd.Panel(data)
Out[127]: 
<class 'pandas.core.panel.Panel'>
Dimensions: 2 (items) x 4 (major_axis) x 3 (minor_axis)
Items axis: Item1 to Item2
Major_axis axis: 0 to 3
Minor_axis axis: 0 to 2

请注意字典中的values只需要能转换成DataFrame就行。因此,上面的DataFrame的构造方法都适用。
一个有用的工厂函数是Panel.from_dict,需要传入上文所说的DataFrame构成的字典,以及下面几个参数:

参数 默认 描述
intersect False 删除索引不对齐的元素
orient items 使用minor来把DataFrame的列作为panel的items

比如,我们和上面的构造做一下对比:

In [128]: pd.Panel.from_dict(data, orient='minor')
Out[128]: 
<class 'pandas.core.panel.Panel'>
Dimensions: 3 (items) x 4 (major_axis) x 2 (minor_axis)
Items axis: 0 to 2
Major_axis axis: 0 to 3
Minor_axis axis: Item1 to Item2

对于混合类型的DataFrame,orient参数尤其有用。如果你传入的字典中的DataFrame的列是混合类型的,所有的数据的类型都会升级到object类型,除非你传入参数orient='minor'.

In [129]: df = pd.DataFrame({'a': ['foo', 'bar', 'baz'],
   .....:                    'b': np.random.randn(3)})
   .....: 

In [130]: df
Out[130]: 
     a         b
0  foo -0.308853
1  bar -0.681087
2  baz  0.377953

In [131]: data = {'item1': df, 'item2': df}

In [132]: panel = pd.Panel.from_dict(data, orient='minor')

In [133]: panel['a']
Out[133]: 
  item1 item2
0   foo   foo
1   bar   bar
2   baz   baz

In [134]: panel['b']
Out[134]: 
      item1     item2
0 -0.308853 -0.308853
1 -0.681087 -0.681087
2  0.377953  0.377953

In [135]: panel['b'].dtypes
Out[135]: 
item1    float64
item2    float64
dtype: object

注意: Panel,通常比Series和DataFrame使用地要少,在未来也将被轻微地忽视。很多DataFrame中能用的方法和可选项在Panel中都用不了。

3.4.3.3 从DataFrame创建,使用to_panel方法

to_panel方法能把有两层索引的DataFrame转换为Panel。

In [136]: midx = pd.MultiIndex(levels=[['one', 'two'], ['x', 'y']],
   .....:                      codes=[[1, 1, 0, 0], [1, 0, 1, 0]])
   .....: 

In [137]: df = pd.DataFrame({'A': [1, 2, 3, 4], 'B': [5, 6, 7, 8]}, index=midx)

In [138]: df.to_panel()
Out[138]: 
<class 'pandas.core.panel.Panel'>
Dimensions: 2 (items) x 2 (major_axis) x 2 (minor_axis)
Items axis: A to B
Major_axis axis: one to two
Minor_axis axis: x to y
3.4.3.4 元素选择/添加/删除

就像DataFrame是由Series构成的字典一样,Panel是由DataFrame构成的字典。

In [139]: wp['Item1']
Out[139]: 
                   A         B         C         D
2000-01-01  1.588931  0.476720  0.473424 -0.242861
2000-01-02 -0.014805 -0.284319  0.650776 -1.461665
2000-01-03 -1.137707 -0.891060 -0.693921  1.613616
2000-01-04  0.464000  0.227371 -0.496922  0.306389
2000-01-05 -2.290613 -1.134623 -1.561819 -0.260838

In [140]: wp['Item3'] = wp['Item1'] / wp['Item2']

插入和删除的api和DataFrame相同。和DataFrame一样,如果item是有效的python标识符,你也可以将它作为属性来访问,并且在IPython中用tab键补全。

3.4.3.5 转置

运用transpose方法能将Panel重组。(默认不会返回一个副本,除非原数据是异质的。)

In [141]: wp.transpose(2, 0, 1)
Out[141]: 
<class 'pandas.core.panel.Panel'>
Dimensions: 4 (items) x 3 (major_axis) x 5 (minor_axis)
Items axis: A to D
Major_axis axis: Item1 to Item3
Minor_axis axis: 2000-01-01 00:00:00 to 2000-01-05 00:00:00
3.4.3.6 索引/选择
操作 语法 结果
选取项 wp[item] DataFrame
在major_axis轴上切片 wp.major_xs(val) DataFrame
在wp.minor_axis轴上切片 wp.minor_xs(val) DataFrame

比如,使用早一些的例子,我们可以这样做:

In [142]: wp['Item1']
Out[142]: 
                   A         B         C         D
2000-01-01  1.588931  0.476720  0.473424 -0.242861
2000-01-02 -0.014805 -0.284319  0.650776 -1.461665
2000-01-03 -1.137707 -0.891060 -0.693921  1.613616
2000-01-04  0.464000  0.227371 -0.496922  0.306389
2000-01-05 -2.290613 -1.134623 -1.561819 -0.260838

In [143]: wp.major_xs(wp.major_axis[2])
Out[143]: 
      Item1     Item2     Item3
A -1.137707  0.800193 -1.421791
B -0.891060  0.782098 -1.139320
C -0.693921 -1.069094  0.649074
D  1.613616 -1.099248 -1.467927

In [144]: wp.minor_axis
Out[144]: Index(['A', 'B', 'C', 'D'], dtype='object')

In [145]: wp.minor_xs('C')
Out[145]: 
               Item1     Item2     Item3
2000-01-01  0.473424 -0.902937 -0.524316
2000-01-02  0.650776 -1.144073 -0.568824
2000-01-03 -0.693921 -1.069094  0.649074
2000-01-04 -0.496922  0.661084 -0.751678
2000-01-05 -1.561819 -1.056652  1.478083
3.4.3.7 压缩

改变维度的另一种方法是压缩一个一维的对象,比如wp['Item1']这样的。

In [146]: wp.reindex(items=['Item1']).squeeze()
Out[146]: 
                   A         B         C         D
2000-01-01  1.588931  0.476720  0.473424 -0.242861
2000-01-02 -0.014805 -0.284319  0.650776 -1.461665
2000-01-03 -1.137707 -0.891060 -0.693921  1.613616
2000-01-04  0.464000  0.227371 -0.496922  0.306389
2000-01-05 -2.290613 -1.134623 -1.561819 -0.260838

In [147]: wp.reindex(items=['Item1'], minor=['B']).squeeze()
Out[147]: 
2000-01-01    0.476720
2000-01-02   -0.284319
2000-01-03   -0.891060
2000-01-04    0.227371
2000-01-05   -1.134623
Freq: D, Name: B, dtype: float64
3.4.3.8 转换为DataFrame

Panel能装换为一个多层次的DataFrame,以2维的表格形式呈现。详情请看多重索引部分.把Panel转换为DataFrame需用到to_frame方法:

In [148]: panel = pd.Panel(np.random.randn(3, 5, 4), items=['one', 'two', 'three'],
   .....:                  major_axis=pd.date_range('1/1/2000', periods=5),
   .....:                  minor_axis=['a', 'b', 'c', 'd'])
   .....: 

In [149]: panel.to_frame()
Out[149]: 
                       one       two     three
major      minor                              
2000-01-01 a      0.493672  1.219492 -1.290493
           b     -2.461467  0.062297  0.787872
           c     -1.553902 -0.110388  1.515707
           d      2.015523 -1.184357 -0.276487
2000-01-02 a     -1.833722 -0.558081 -0.223762
           b      1.771740  0.077849  1.397431
           c     -0.670027  0.629498  1.503874
           d      0.049307 -1.035260 -0.478905
2000-01-03 a     -0.521493 -0.438229 -0.135950
           b     -3.201750  0.503703 -0.730327
           c      0.792716  0.413086 -0.033277
           d      0.146111 -1.139050  0.281151
2000-01-04 a      1.903247  0.660342 -1.298915
           b     -0.747169  0.464794 -2.819487
           c     -0.309038 -0.309337 -0.851985
           d      0.393876 -0.649593 -1.106952
2000-01-05 a      1.861468  0.683758 -0.937731
           b      0.936527 -0.643834 -1.537770
           c      1.255746  0.421287  0.555759
           d     -2.655452  1.032814 -2.277282

3.4.4 弃用面板(Deprecate Panel)

在过去的一些年里,pandas在深度和广度上都取得了发展,带来了新的特性、数据类型以及操作程序。因此,为了支持Series、DataFrame和Panel的高效索引和函数程序,我们不得不面对逐渐增加的碎片化和难以理解的代码基。
3维的Panel结构,相比于1维的Series和2维的DataFrame,对于许多数据分析来说不那么常见。因此在未来pandas将专注于1维和2维的数据结构。
通常情况下,用户能够使用多重索引的DataFrame来轻松处理高纬度的数据。
此外,xarray包从一开始就是为支持多维数据的分析而构建的,已经涵盖了Panel的主要用途。这里是xarray的panel转换文档.

In [150]: import pandas.util.testing as tm

In [151]: p = tm.makePanel()

In [152]: p
Out[152]: 
<class 'pandas.core.panel.Panel'>
Dimensions: 3 (items) x 30 (major_axis) x 4 (minor_axis)
Items axis: ItemA to ItemC
Major_axis axis: 2000-01-03 00:00:00 to 2000-02-11 00:00:00
Minor_axis axis: A to D

转换为多重索引的DataFrame。

In [153]: p.to_frame()
Out[153]: 
                     ItemA     ItemB     ItemC
major      minor                              
2000-01-03 A     -0.390201 -1.624062 -0.605044
           B      1.562443  0.483103  0.583129
           C     -1.085663  0.768159 -0.273458
           D      0.136235 -0.021763 -0.700648
2000-01-04 A      1.207122 -0.758514  0.878404
           B      0.763264  0.061495 -0.876690
           C     -1.114738  0.225441 -0.335117
           D      0.886313 -0.047152 -1.166607
2000-01-05 A      0.178690 -0.560859 -0.921485
           B      0.162027  0.240767 -1.919354
           C     -0.058216  0.543294 -0.476268
           D     -1.350722  0.088472 -0.367236
2000-01-06 A     -1.004168 -0.589005 -0.200312
           B     -0.902704  0.782413 -0.572707
           C     -0.486768  0.771931 -1.765602
           D     -0.886348 -0.857435  1.296674
2000-01-07 A     -1.377627 -1.070678  0.522423
           B      1.106010  0.628462 -1.736484
           C      1.685148 -0.968145  0.578223
           D     -1.013316 -2.503786  0.641385
2000-01-10 A      0.499281 -1.681101  0.722511
           B     -0.199234 -0.880627 -1.335113
           C      0.112572 -1.176383  0.242697
           D      1.920906 -1.058041 -0.779432
2000-01-11 A     -1.405256  0.403776 -1.702486
           B      0.458265  0.777575 -1.244471
           C     -1.495309 -3.192716  0.208129
           D     -0.388231 -0.657981  0.602456
2000-01-12 A      0.162565  0.609862 -0.709535
           B      0.491048 -0.779367  0.347339
...                    ...       ...       ...
2000-02-02 C     -0.303961 -0.463752 -0.288962
           D      0.104050  1.116086  0.506445
2000-02-03 A     -2.338595 -0.581967 -0.801820
           B     -0.557697 -0.033731 -0.176382
           C      0.625555 -0.055289  0.875359
           D      0.174068 -0.443915  1.626369
2000-02-04 A     -0.374279 -1.233862 -0.915751
           B      0.381353 -1.108761 -1.970108
           C     -0.059268 -0.360853 -0.614618
           D     -0.439461 -0.200491  0.429518
2000-02-07 A     -2.359958 -3.520876 -0.288156
           B      1.337122 -0.314399 -1.044208
           C      0.249698  0.728197  0.565375
           D     -0.741343  1.092633  0.013910
2000-02-08 A     -1.157886  0.516870 -1.199945
           B     -1.531095 -0.860626 -0.821179
           C      1.103949  1.326768  0.068184
           D     -0.079673 -1.675194 -0.458272
2000-02-09 A     -0.551865  0.343125 -0.072869
           B      1.331458  0.370397 -1.914267
           C     -1.087532  0.208927  0.788871
           D     -0.922875  0.437234 -1.531004
2000-02-10 A      1.592673  2.137827 -1.828740
           B     -0.571329 -1.761442 -0.826439
           C      1.998044  0.292058 -0.280343
           D      0.303638  0.388254 -0.500569
2000-02-11 A      1.559318  0.452429 -1.716981
           B     -0.026671 -0.899454  0.124808
           C     -0.244548 -2.019610  0.931536
           D     -0.917368  0.479630  0.870690

[120 rows x 3 columns]

或者,你也可以将Panel转换为xarray的DataArray。

In [154]: p.to_xarray()
Out[154]: 
<xarray.DataArray (items: 3, major_axis: 30, minor_axis: 4)>
array([[[-0.390201,  1.562443, -1.085663,  0.136235],
        [ 1.207122,  0.763264, -1.114738,  0.886313],
        ..., 
        [ 1.592673, -0.571329,  1.998044,  0.303638],
        [ 1.559318, -0.026671, -0.244548, -0.917368]],

       [[-1.624062,  0.483103,  0.768159, -0.021763],
        [-0.758514,  0.061495,  0.225441, -0.047152],
        ..., 
        [ 2.137827, -1.761442,  0.292058,  0.388254],
        [ 0.452429, -0.899454, -2.01961 ,  0.47963 ]],

       [[-0.605044,  0.583129, -0.273458, -0.700648],
        [ 0.878404, -0.87669 , -0.335117, -1.166607],
        ..., 
        [-1.82874 , -0.826439, -0.280343, -0.500569],
        [-1.716981,  0.124808,  0.931536,  0.87069 ]]])
Coordinates:
  * items       (items) object 'ItemA' 'ItemB' 'ItemC'
  * major_axis  (major_axis) datetime64[ns] 2000-01-03 2000-01-04 ... 2000-02-11
  * minor_axis  (minor_axis) object 'A' 'B' 'C' 'D'

详情请看xarray包的文档.

上一篇下一篇

猜你喜欢

热点阅读