数据结构

这一节介绍pandas中的数据结构。首先,导入numpy和pandas:


In [1]:
import numpy as np
import pandas as pd

我们先对数据结构进行简短的介绍, 然后再详细说明各个数据结构内置的方法。

Series

Series是一个一维带label的数组,元素可以是任何数据类型(整数、字符串、浮点数,Python对象等等)。和Python列表一样,Series元素的数据类型可以不同。Series是值可变的数据结构,你可以对它的值进行修改,但是Series的大小是不可以改变的。

Series的label就是index。

创建一个Series对象:

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

这里,data可以是:

  • Python字典
  • ndarray
  • 标量数值(比如5)

传入的index是label组成的列表。 因此,依据data的不同,我们可以分成以下几种情形:

ndarray

如果data是一个ndarray,index的长度必须和data一样。若没有指明index,则默认创建一个 [0, ..., len(data) - 1]的index。


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


Out[2]:
a   -0.896537
b   -0.138583
c    0.364762
d    0.683769
e   -1.473285
dtype: float64

In [3]:
s.index


Out[3]:
Index([u'a', u'b', u'c', u'd', u'e'], dtype='object')

In [4]:
pd.Series(np.random.randn(5))


Out[4]:
0   -0.301565
1    0.135762
2    0.197967
3    1.100039
4    0.351633
dtype: float64

注意: 从0.8.0版本开始,index的值可以重复。


In [6]:
pd.Series(np.random.randn(3), index=['a', 'b', 'a'])


Out[6]:
a    1.688700
b   -1.138083
a   -0.976848
dtype: float64

dict字典

如果dict是字典,index的长度可以和data长度不同,也可以不提供index:


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


Out[9]:
a    0.0
b    1.0
c    2.0
dtype: float64

In [10]:
pd.Series(d, index=['b', 'c', 'd', 'a'])


Out[10]:
b    1.0
c    2.0
d    NaN
a    0.0
dtype: float64

注意: NaN(not a number)是pandas中缺失值标记。

标量数值

如果data是一个标量值,必须提供index。为了匹配index的长度,该数值将被重复。


In [11]:
pd.Series(5., index=['a', 'b', 'c', 'd', 'e'])


Out[11]:
a    5.0
b    5.0
c    5.0
d    5.0
e    5.0
dtype: float64

Series vs ndarray

大多数情况下,你都可以把Series看做一个ndarray来处理。甚至,大多数的NumPy函数都支持Series作参数。


In [17]:
s[0]


Out[17]:
-0.89653676398012794

In [18]:
s[:3]


Out[18]:
a   -0.896537
b   -0.138583
c    0.364762
dtype: float64

In [19]:
s[s > s.median()]


Out[19]:
c    0.364762
d    0.683769
dtype: float64

In [20]:
s[[4,3,1]]


Out[20]:
e   -1.473285
d    0.683769
b   -0.138583
dtype: float64

In [21]:
np.exp(s)


Out[21]:
a    0.407980
b    0.870591
c    1.440172
d    1.981331
e    0.229171
dtype: float64

Series vs dict

你可以把Series看做一个长度固定的字典,你可以通过index来获取和设置数值:


In [22]:
s['a']


Out[22]:
-0.89653676398012794

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

In [24]:
s


Out[24]:
a    -0.896537
b    -0.138583
c     0.364762
d     0.683769
e    12.000000
dtype: float64

In [25]:
'e' in s


Out[25]:
True

In [26]:
'f' in s


Out[26]:
False

如果label值不存在,将抛出异常:


In [27]:
s['f']


---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
<ipython-input-27-f7a405991146> in <module>()
----> 1 s['f']

/Users/lj/.pyenv/versions/2.7.12/lib/python2.7/site-packages/pandas/core/series.pyc in __getitem__(self, key)
    601         key = com._apply_if_callable(key, self)
    602         try:
--> 603             result = self.index.get_value(self, key)
    604 
    605             if not is_scalar(result):

/Users/lj/.pyenv/versions/2.7.12/lib/python2.7/site-packages/pandas/indexes/base.pyc in get_value(self, series, key)
   2181                     raise InvalidIndexError(key)
   2182                 else:
-> 2183                     raise e1
   2184             except Exception:  # pragma: no cover
   2185                 raise e1

KeyError: 'f'

使用get方法,遇到缺失的label将返回None或指定值:


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

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


Out[29]:
nan

向量操作和label对齐

进行数据分析时,你可以把Series看做向量进行整体操作。大多数接受ndarray作参数的NumPy方法也支持传入Series对象


In [30]:
s + s


Out[30]:
a    -1.793074
b    -0.277166
c     0.729524
d     1.367538
e    24.000000
dtype: float64

In [31]:
s * 2


Out[31]:
a    -1.793074
b    -0.277166
c     0.729524
d     1.367538
e    24.000000
dtype: float64

In [32]:
np.exp(s)


Out[32]:
a         0.407980
b         0.870591
c         1.440172
d         1.981331
e    162754.791419
dtype: float64

Series和ndarray之间的主要区别是,Series之间的操作会基于label对数据自动对齐。

所以,你不需要考虑两个参与计算的Series是否有完全相同的label。


In [34]:
s[1:] + s[:-1]


Out[34]:
a         NaN
b   -0.277166
c    0.729524
d    1.367538
e         NaN
dtype: float64

如果两个label不一样的Series参与计算,存储结果的Series的index/label是它们俩的union(并集)。正是自带label对齐,才使得pandas区别于大多数数据分析库,优越性一览无余。

name属性

Series构造函数还有另一个参数:name,


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

In [32]:
s


Out[32]:
0   -0.198564
1   -0.024818
2    0.220382
3    1.227965
4    0.690763
Name: something, dtype: float64

In [36]:
s.name


Out[36]:
'something'

通过pandas.Series.rename()方法,可以给Series重命名。


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

s2.name


Out[37]:
'different'

In [38]:
s.name


Out[38]:
'something'

注意s和s2是两个不同对象。

DataFrame

DataFrame是一个带label的二维数据结构。你可以把它看做一张SQL表,或是由Series构成的字典。它基本上是最常用的pandas数据结构。

和Series一样,DataFrame构造函数支持许多不同类型的输入:

  • 字典,可以是普通字典,或者一维ndarray字典、列表字典、Series字典
  • 二维numpy.ndarray
  • 结构化或记录化的ndarray
  • 字典列表
  • 一个Series
  • DataFrame

DataFrame构造函数也支持传入index(行label)和columns(列label)参数。

Series字典或字典

结果的index是各个Series的index的union。如果存在任何嵌套类型的字典,将首先转换成Series。如果不传入columns,则默认把字典的键构成的有序列表看做columns。


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

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

In [41]:
df


Out[41]:
one two
a 1.0 1.0
b 2.0 2.0
c 3.0 3.0
d NaN 4.0

In [42]:
pd.DataFrame(d, index=['d','b','a'])


Out[42]:
one two
d NaN 4.0
b 2.0 2.0
a 1.0 1.0

In [44]:
pd.DataFrame(d, index=['d', 'b', 'a'], columns=['two', 'three'])


Out[44]:
two three
d 4.0 NaN
b 2.0 NaN
a 1.0 NaN

行label和列label可分别通过访问index和columns获取:


In [45]:
df.index


Out[45]:
Index([u'a', u'b', u'c', u'd'], dtype='object')

In [46]:
df.columns


Out[46]:
Index([u'one', u'two'], dtype='object')

ndarray字典 列表字典

ndarrays必须具有相同的长度。如果传入index参数,它的长度也必须和ndarray长度相同。如果不传入index参数,DataFrame会默认创建index=range(n),其中n是ndarray的长度。


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

In [49]:
pd.DataFrame(d)


Out[49]:
one two
0 1.0 4.0
1 2.0 3.0
2 3.0 2.0
3 4.0 1.0

In [51]:
pd.DataFrame(d, index=['a', 'b', 'c', 'd'])


Out[51]:
one two
a 1.0 4.0
b 2.0 3.0
c 3.0 2.0
d 4.0 1.0

结构化或记录ndarray


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

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

pd.DataFrame(data)


Out[52]:
A B C
0 1 2.0 Hello
1 2 3.0 World

In [53]:
pd.DataFrame(data, index=['first','second'])


Out[53]:
A B C
first 1 2.0 Hello
second 2 3.0 World

In [54]:
pd.DataFrame(data, columns=['C','A','B'])


Out[54]:
C A B
0 Hello 1 2.0
1 World 2 3.0

字典列表


In [55]:
data2 = [{'a': 1, 'b': 2}, {'a': 5, 'b': 10, 'c': 20}]

In [56]:
pd.DataFrame(data2)


Out[56]:
a b c
0 1 2 NaN
1 5 10 20.0

In [57]:
pd.DataFrame(data2, index=['first','second'])


Out[57]:
a b c
first 1 2 NaN
second 5 10 20.0

In [58]:
pd.DataFrame(data2, columns=['a','b'])


Out[58]:
a b
0 1 2
1 5 10

元组字典


In [59]:
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[59]:
a b
a b c a b
A B 4.0 1.0 5.0 8.0 10.0
C 3.0 2.0 6.0 7.0 NaN
D NaN NaN NaN NaN 9.0

Series

结果是创建一个列数为1的DataFrame,它的index和输入的Series相同,column名是Series的name。

其他的构造函数

DataFrame.from_dict

DataFrame.from_dict接受字典的字典或数组序列的字典,并返回一个DataFrame。

DataFrame.from_records

DataFrame.from_records接受一个元组列表或结构化类型的ndarray。例如:


In [60]:
data


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

In [61]:
pd.DataFrame.from_records(data, index='C')


Out[61]:
A B
C
Hello 1 2.0
World 2 3.0

DataFrame.from_items


In [62]:
pd.DataFrame.from_items([('A', [1, 2, 3]), ('B', [4, 5, 6])])


Out[62]:
A B
0 1 4
1 2 5
2 3 6

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


Out[63]:
one two three
A 1 2 3
B 4 5 6

列选择,添加,删除

你可以把DataFrame看做Series构成的字典,使用和字典同样的操作来增加列、删除列、对列重新赋值:


In [64]:
df['one']


Out[64]:
a    1.0
b    2.0
c    3.0
d    NaN
Name: one, dtype: float64

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

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

In [67]:
df


Out[67]:
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 [68]:
del df['two']

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

In [70]:
df


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

当插入一个标量值,它自然会被填充到列中


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

In [72]:
df


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

当插入不具有相同的index的Series时,将服从该DataFrame的索引:


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

In [74]:
df


Out[74]:
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的index长度相匹配。

缺省情况下,列被插在末端。insert()函数可以允许插入到指定的列位置:


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

In [76]:
df


Out[76]:
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

用方法链来分配新列

DataFrame有一个assign()方法,利用现有列来创建新列。

iris = pd.read_csv('data/iris.data')

iris.head()

(iris.assign(sepal_ratio = iris['SepalWidth'] / iris['SepalLength']) .head())

iris.assign(sepal_ratio = lambda x: (x['SepalWidth'] / x['SepalLength'])).head()

(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'))

检索

检索的基础知识如下:

操作 语法 结果
列选择 df[col] Series
通过label来选择行 df.loc[label] Series
通过下标选择行 df.iloc[loc] Series
选择部分行 df[5:10] DataFrame
通过布尔向量选择行 df[bool_vec] DataFrame

行选择,例如,返回一个index为DataFrame columns的Series:


In [78]:
df


Out[78]:
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

In [79]:
df.loc['b']


Out[79]:
one              2
bar              2
flag         False
foo            bar
one_trunc        2
Name: b, dtype: object

In [80]:
df.iloc[2]


Out[80]:
one             3
bar             3
flag         True
foo           bar
one_trunc     NaN
Name: c, dtype: object

数据对齐和运算

DataFrame对象之间会自动对index和column进行数据对齐。运算结果的index和columns分别是参与运算的DataFrame的index和columns的并集(union)。


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

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

In [83]:
df + df2


Out[83]:
A B C D
0 1.788448 -1.318960 -0.863117 NaN
1 -1.232623 -2.767670 -0.692324 NaN
2 1.891635 2.348168 -1.476718 NaN
3 -1.133709 1.391048 -0.852821 NaN
4 -0.737702 -2.086597 -0.048224 NaN
5 2.493783 1.733949 -0.199473 NaN
6 -1.715905 2.911299 1.637124 NaN
7 NaN NaN NaN NaN
8 NaN NaN NaN NaN
9 NaN NaN NaN NaN

DataFrame与Series进行运算时, 默认行为是DataFrame的column和Series的index对齐,也就是对Series进行行广播。例如:


In [85]:
df - df.iloc[0]


Out[85]:
A B C D
0 0.000000 0.000000 0.000000 0.000000
1 -0.916674 0.109265 -0.546100 -0.980304
2 0.562543 2.127558 -0.941984 -2.856520
3 -1.869603 0.987336 -0.692732 -2.707851
4 -0.442635 -1.243752 0.185410 -2.947229
5 1.053451 2.104129 -0.729916 -2.641122
6 -1.149715 2.501486 -0.381146 -3.164426
7 -1.097801 1.346510 0.793628 -3.966100
8 -1.748342 0.890703 -0.460997 0.393845
9 -0.671883 -0.465574 -1.898304 -2.865972

在特殊情况下, 处理时间序列数据时, DataFrame的index包含日期,广播会变成列广播:


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

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

In [96]:
df


Out[96]:
A B C
2000-01-01 -1.068166 -0.589251 1.147851
2000-01-02 0.056043 -1.373088 0.380902
2000-01-03 -0.662745 -1.652106 0.831692
2000-01-04 0.060417 -0.945642 1.365181
2000-01-05 1.530166 -1.364481 -1.049081
2000-01-06 -0.091011 -0.373622 -0.595570
2000-01-07 -0.648845 -0.677954 0.217878
2000-01-08 -1.282067 0.462022 -0.429438

In [97]:
type(df['A'])


Out[97]:
pandas.core.series.Series

In [98]:
df - df['A']


Out[98]:
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-06 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 NaN
2000-01-02 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2000-01-03 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2000-01-04 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2000-01-05 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2000-01-06 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2000-01-07 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2000-01-08 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN

In [104]:
df.sub(df['A'], axis=0) #


Out[104]:
A B C
2000-01-01 0.0 0.478915 2.216017
2000-01-02 0.0 -1.429131 0.324859
2000-01-03 0.0 -0.989361 1.494438
2000-01-04 0.0 -1.006059 1.304764
2000-01-05 0.0 -2.894647 -2.579247
2000-01-06 0.0 -0.282611 -0.504559
2000-01-07 0.0 -0.029109 0.866723
2000-01-08 0.0 1.744090 0.852630

In [100]:
df * 5 + 2


Out[100]:
A B C
2000-01-01 -3.340832 -0.946257 7.739253
2000-01-02 2.280217 -4.865441 3.904511
2000-01-03 -1.313726 -6.260532 6.158462
2000-01-04 2.302084 -2.728210 8.825904
2000-01-05 9.650829 -4.822407 -3.245405
2000-01-06 1.544947 0.131891 -0.977850
2000-01-07 -1.244225 -1.389769 3.089392
2000-01-08 -4.410336 4.310112 -0.147188

In [101]:
1 / df


Out[101]:
A B C
2000-01-01 -0.936184 -1.697069 0.871194
2000-01-02 17.843329 -0.728285 2.625346
2000-01-03 -1.508876 -0.605288 1.202367
2000-01-04 16.551678 -1.057483 0.732504
2000-01-05 0.653524 -0.732879 -0.953215
2000-01-06 -10.987734 -2.676503 -1.679064
2000-01-07 -1.541200 -1.475027 4.589717
2000-01-08 -0.779990 2.164398 -2.328627

In [102]:
df ** 4


Out[102]:
A B C
2000-01-01 1.301834 0.120560 1.735967
2000-01-02 0.000010 3.554624 0.021050
2000-01-03 0.192924 7.449927 0.478466
2000-01-04 0.000013 0.799663 3.473446
2000-01-05 5.482189 3.466336 1.211257
2000-01-06 0.000069 0.019486 0.125815
2000-01-07 0.177241 0.211252 0.002253
2000-01-08 2.701738 0.045567 0.034010

布尔运算


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

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

In [107]:
df1 & df2


Out[107]:
a b
0 False False
1 False True
2 True False

In [108]:
df1 | df2


Out[108]:
a b
0 True True
1 True True
2 True True

In [109]:
df1 ^ df2


Out[109]:
a b
0 True True
1 True False
2 False True

In [110]:
-df1


Out[110]:
a b
0 False True
1 True False
2 False False

转置

转置, T属性(转置函数):


In [111]:
df[:5].T


Out[111]:
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
A -1.068166 0.056043 -0.662745 0.060417 1.530166
B -0.589251 -1.373088 -1.652106 -0.945642 -1.364481
C 1.147851 0.380902 0.831692 1.365181 -1.049081

DataFrame与NumPy函数的互用性


In [112]:
df


Out[112]:
A B C
2000-01-01 -1.068166 -0.589251 1.147851
2000-01-02 0.056043 -1.373088 0.380902
2000-01-03 -0.662745 -1.652106 0.831692
2000-01-04 0.060417 -0.945642 1.365181
2000-01-05 1.530166 -1.364481 -1.049081
2000-01-06 -0.091011 -0.373622 -0.595570
2000-01-07 -0.648845 -0.677954 0.217878
2000-01-08 -1.282067 0.462022 -0.429438

In [113]:
np.exp(df)


Out[113]:
A B C
2000-01-01 0.343638 0.554742 3.151412
2000-01-02 1.057644 0.253323 1.463604
2000-01-03 0.515434 0.191646 2.297203
2000-01-04 1.062279 0.388430 3.916431
2000-01-05 4.618943 0.255513 0.350259
2000-01-06 0.913008 0.688237 0.551248
2000-01-07 0.522649 0.507655 1.243436
2000-01-08 0.277463 1.587281 0.650875

In [114]:
np.asarray(df)


Out[114]:
array([[-1.06816643, -0.58925135,  1.14785062],
       [ 0.05604335, -1.37308812,  0.38090214],
       [-0.66274516, -1.65210639,  0.83169249],
       [ 0.06041683, -0.945642  ,  1.36518073],
       [ 1.53016581, -1.3644815 , -1.04908109],
       [-0.09101057, -0.37362184, -0.59557005],
       [-0.64884494, -0.67795373,  0.21787835],
       [-1.28206723,  0.46202231, -0.42943764]])

dot方法能够实现DataFrame矩阵乘法:


In [115]:
df.T.dot(df)


Out[115]:
A B C
A 6.001388 -0.616077 -2.815335
B -0.616077 8.530771 -2.556553
C -2.815335 -2.556553 5.705241

类似地,dot方法也能运用在Series上:


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

In [117]:
s1.dot(s1)


Out[117]:
255

控制台显示

在控制台,非常大的DataFrames将被截断显示它们。你也可以使用info()查看详情。

baseball = pd.read_csv('data/baseball.csv')

print(baseball)

baseball.info()

然而,使用to_string,DataFrame将返回一个字符串表示的表格形式,虽然它并不总是适合控制台宽度:

print(baseball.iloc[-20:, :12].to_string())

pd.DataFrame(np.random.randn(3, 12))

你可以设置display.width值,来改变单行打印的数量。

pd.set_option('display.width', 40)

pd.DataFrame(np.random.randn(3, 12))

DataFrame列属性访问

如果DataFrame的列名是一个有效的Python变量名, 就可以像访问属性一样访问列数据:


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

In [119]:
df


Out[119]:
foo1 foo2
0 1.452653 -0.182980
1 0.596190 -1.162197
2 -0.502700 -0.003133
3 -0.612586 -1.664574
4 0.950622 -0.802543

In [121]:
df.foo1


Out[121]:
0    1.452653
1    0.596190
2   -0.502700
3   -0.612586
4    0.950622
Name: foo1, dtype: float64

Panel

Panel比较少用,但是对于三维数据很有用。


In [ ]:


In [ ]:


In [ ]:


In [ ]:


In [ ]: