Series

In [20]:
import numpy as np
import pandas as pd
obj = pd.Series([4,7,-5,3])
In [21]:
# 通过values属性和index属性分别获得Series对象的值和索引
obj.index
Out[21]:
RangeIndex(start=0, stop=4, step=1)
In [22]:
obj.values
Out[22]:
array([ 4,  7, -5,  3])
In [23]:
obj2 = pd.Series([4, 7, -5, 3], index = ['d','b','a','c'])
obj2
Out[23]:
d    4
b    7
a   -5
c    3
dtype: int64
In [24]:
# 与NumPy相比,可以从数据中选择数据的时候使用标签来进行索引
obj2['a']
Out[24]:
-5
In [25]:
obj2['d'] = 6
obj2[['c','a','d']]
Out[25]:
c    3
a   -5
d    6
dtype: int64
In [26]:
obj2[obj2 > 0]
Out[26]:
d    6
b    7
c    3
dtype: int64
In [27]:
obj2 * 2
Out[27]:
d    12
b    14
a   -10
c     6
dtype: int64
In [28]:
np.exp(obj2)
Out[28]:
d     403.428793
b    1096.633158
a       0.006738
c      20.085537
dtype: float64

从另一个角度考虑Series,可以认为它是一个长度固定且有序的词典,因为它将索引值和数据值按位置配对。在你可能会使用字典的上下文中,可以使用Series

In [29]:
'b' in obj2
Out[29]:
True
In [30]:
# 如果已经有数据在Python字典中,可以使用字典生成一个Series
sdata = {'Ohio':35000, 'Texas':71000, 'Oregon':16000,'Utah':5000}
obj3 = pd.Series(sdata)
obj3
Out[30]:
Ohio      35000
Texas     71000
Oregon    16000
Utah       5000
dtype: int64

当把字典传递给Series构造函数时,产成的Series的索引将是排序好的字典键。可以将字典键按照所想要的顺序传递给构造函数,从而生产的Series的索引顺序符合你的预期

In [31]:
states = ['California','Ohio','Oregon','Texas']
obj4 = pd.Series(sdata, index = states)
obj4
Out[31]:
California        NaN
Ohio          35000.0
Oregon        16000.0
Texas         71000.0
dtype: float64
In [32]:
# 使用isnull和notnull函数来检查缺失数据
pd.isnull(obj4)
Out[32]:
California     True
Ohio          False
Oregon        False
Texas         False
dtype: bool
In [33]:
pd.notnull(obj4)
Out[33]:
California    False
Ohio           True
Oregon         True
Texas          True
dtype: bool
In [34]:
# isnull和nutll也是Series的方法
obj4.isnull()
Out[34]:
California     True
Ohio          False
Oregon        False
Texas         False
dtype: bool
In [35]:
obj4.notnull()
Out[35]:
California    False
Ohio           True
Oregon         True
Texas          True
dtype: bool
In [36]:
obj3
Out[36]:
Ohio      35000
Texas     71000
Oregon    16000
Utah       5000
dtype: int64
In [37]:
obj4
Out[37]:
California        NaN
Ohio          35000.0
Oregon        16000.0
Texas         71000.0
dtype: float64
In [38]:
obj3 + obj4
Out[38]:
California         NaN
Ohio           70000.0
Oregon         32000.0
Texas         142000.0
Utah               NaN
dtype: float64
In [39]:
# Series对象自身和其索引都有name属性,这个属性与pandas其他重要功能集成在一起
obj4.name = 'population'
obj4.index.name = 'state'
In [40]:
obj4
Out[40]:
state
California        NaN
Ohio          35000.0
Oregon        16000.0
Texas         71000.0
Name: population, dtype: float64
In [41]:
# Series的索引可以按照位置赋值的方式进行改变
obj
Out[41]:
0    4
1    7
2   -5
3    3
dtype: int64
In [42]:
obj.index = ['Bob','Steve','Jeff','Ryan']
obj
Out[42]:
Bob      4
Steve    7
Jeff    -5
Ryan     3
dtype: int64

DataFrame

有多种方式可以构建DataFrame,其中最常用的方式是利用包含等长度列表或NumPy数组的字典来形成DataFrame

In [43]:
data = {'state':['Ohio','Ohio','Ohio','Nevada','Nevada','Nevada'],
       'year':[2000,2001,2002,2001,2002,2003],
       'pop':[1.5, 1.7, 3.6, 2.4, 2.9,3.2]}
frame = pd.DataFrame(data)
In [44]:
frame
Out[44]:
state year pop
0 Ohio 2000 1.5
1 Ohio 2001 1.7
2 Ohio 2002 3.6
3 Nevada 2001 2.4
4 Nevada 2002 2.9
5 Nevada 2003 3.2
In [45]:
frame.head()
Out[45]:
state year pop
0 Ohio 2000 1.5
1 Ohio 2001 1.7
2 Ohio 2002 3.6
3 Nevada 2001 2.4
4 Nevada 2002 2.9
In [46]:
pd.DataFrame(data, columns=['year','state','pop'])
Out[46]:
year state pop
0 2000 Ohio 1.5
1 2001 Ohio 1.7
2 2002 Ohio 3.6
3 2001 Nevada 2.4
4 2002 Nevada 2.9
5 2003 Nevada 3.2
In [47]:
# 如果传的列不包含在字典中,将会在结果中出现缺失值
frame2 = pd.DataFrame(data, columns = ['year','state','pop','debt'],
                     index = ['one','two','three','four','five','six'])
frame2
Out[47]:
year state pop debt
one 2000 Ohio 1.5 NaN
two 2001 Ohio 1.7 NaN
three 2002 Ohio 3.6 NaN
four 2001 Nevada 2.4 NaN
five 2002 Nevada 2.9 NaN
six 2003 Nevada 3.2 NaN
In [48]:
frame2.columns
Out[48]:
Index(['year', 'state', 'pop', 'debt'], dtype='object')
In [49]:
frame2['state']
Out[49]:
one        Ohio
two        Ohio
three      Ohio
four     Nevada
five     Nevada
six      Nevada
Name: state, dtype: object
In [50]:
frame2.state
Out[50]:
one        Ohio
two        Ohio
three      Ohio
four     Nevada
five     Nevada
six      Nevada
Name: state, dtype: object
In [51]:
frame2['debt'] = 15
frame2
Out[51]:
year state pop debt
one 2000 Ohio 1.5 15
two 2001 Ohio 1.7 15
three 2002 Ohio 3.6 15
four 2001 Nevada 2.4 15
five 2002 Nevada 2.9 15
six 2003 Nevada 3.2 15

当将列表或数组赋值给一个列时,值的长度必须和DataFrame的长度相匹配。如果将Series赋值给一列时,Series的索引将会按照DataFrame的索引重新排列,并在空缺的地方填充缺失值

In [52]:
val = pd.Series([-1.2, -1.5, -1.7], index = ['two','four','five'])
frame2['debt'] = val
frame2
Out[52]:
year state pop debt
one 2000 Ohio 1.5 NaN
two 2001 Ohio 1.7 -1.2
three 2002 Ohio 3.6 NaN
four 2001 Nevada 2.4 -1.5
five 2002 Nevada 2.9 -1.7
six 2003 Nevada 3.2 NaN
In [53]:
# del删除列
frame2['eastern'] = frame2.state == 'Ohio'
frame2
Out[53]:
year state pop debt eastern
one 2000 Ohio 1.5 NaN True
two 2001 Ohio 1.7 -1.2 True
three 2002 Ohio 3.6 NaN True
four 2001 Nevada 2.4 -1.5 False
five 2002 Nevada 2.9 -1.7 False
six 2003 Nevada 3.2 NaN False
In [54]:
del frame2['eastern']
frame2.columns
Out[54]:
Index(['year', 'state', 'pop', 'debt'], dtype='object')

从DataFrame中选取的列是数据的视图,而不是拷贝。因此,对Series的修改会映射到DataFrame中,如果需要复制,则应当显示的使用Series的copy方法

另一种常用的数据形式是包含字典的嵌套字典

In [55]:
pop = {'Nevada':{2001:2.4,2002:2.9},
      'Ohio':{2000:1.5,2001:1.7,2002:3.6}}
pop
Out[55]:
{'Nevada': {2001: 2.4, 2002: 2.9}, 'Ohio': {2000: 1.5, 2001: 1.7, 2002: 3.6}}
In [56]:
# 如果嵌套字典被赋值给DataFrame,pandas会将字典的键作为i列,将内部字典的键作为行索引
frame3 = pd.DataFrame(pop)
In [57]:
frame3
Out[57]:
Nevada Ohio
2000 NaN 1.5
2001 2.4 1.7
2002 2.9 3.6
In [58]:
frame3.T
Out[58]:
2000 2001 2002
Nevada NaN 2.4 2.9
Ohio 1.5 1.7 3.6

包含Series的字典也可以用于构造DataFrame

In [59]:
pdata = {'Ohio':frame3['Ohio'][:-1],
         'Nevada':frame3['Nevada'][:-1]}
pd.DataFrame(pdata)
Out[59]:
Ohio Nevada
2000 1.5 NaN
2001 1.7 2.4
In [60]:
# 如果DataFrame的索引和列拥有name属性,则这些name属性也会被显示
frame3.index.name = 'year'
frame3.name = 'state'
frame3
Out[60]:
Nevada Ohio
year
2000 NaN 1.5
2001 2.4 1.7
2002 2.9 3.6
In [61]:
# 和Series类似,DataFrame的values属性会将包含在DataFrame中的数据以二维ndarray的形式返回
frame3.values
Out[61]:
array([[nan, 1.5],
       [2.4, 1.7],
       [2.9, 3.6]])
In [62]:
# 如果DataFrame的列是不同的dtypes,则values的dtype会自动选择适合所有列的类型
frame2.values
Out[62]:
array([[2000, 'Ohio', 1.5, nan],
       [2001, 'Ohio', 1.7, -1.2],
       [2002, 'Ohio', 3.6, nan],
       [2001, 'Nevada', 2.4, -1.5],
       [2002, 'Nevada', 2.9, -1.7],
       [2003, 'Nevada', 3.2, nan]], dtype=object)

索引对象

pandas中索引对象是用于存储轴标签和其他元数据的,在构造Series或DataFrame时,所使用的任意数组或标签序列都可以在内部转换为索引对象

In [5]:
import pandas as pd
import numpy as np
obj = pd.Series(range(3), index = ['a','b','c'])
index = obj.index
In [2]:
index
Out[2]:
Index(['a', 'b', 'c'], dtype='object')
In [3]:
index[1:]
Out[3]:
Index(['b', 'c'], dtype='object')
In [4]:
#索引对象是不可变的,因此用户是无法修改索引的对象
index[1] = 'd'
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-4-a86224e15476> in <module>
      1 #索引对象是不可变的,因此用户是无法修改索引的对象
----> 2 index[1] = 'd'

~/anaconda3/lib/python3.7/site-packages/pandas/core/indexes/base.py in __setitem__(self, key, value)
   3936 
   3937     def __setitem__(self, key, value):
-> 3938         raise TypeError("Index does not support mutable operations")
   3939 
   3940     def __getitem__(self, key):

TypeError: Index does not support mutable operations
In [6]:
# 不可变性使得在多种数据结构中分享索引对象更为安全
labels = pd.Index(np.arange(3))
labels
Out[6]:
Int64Index([0, 1, 2], dtype='int64')
In [7]:
obj2 = pd.Series([1.5, -2.5, 0], index = labels)
obj2
Out[7]:
0    1.5
1   -2.5
2    0.0
dtype: float64

除了类似数组,索引对象也像一个固定大小的集合。与Python集合不同,pandas索引对象可以包含重复标签。

每个索引都有一些集合逻辑的方法和属性。这些方法和属性解决了关于它所包含的数据的其他常见问题

一些索引对象的方法和属性

  • append

  • difference:计算两个索引的差集

  • intersection:计算两个索引的交集

  • union: 计算两个索引的并集

  • isin: 计算表示每一个值是否在传值容器中的布尔数组

  • delete: 将位置i的元素删除,并产生新的索引

  • drop: 根据传参删除指定索引值,并产生新的索引

  • insert: 在位置i插入元素,并产生新的索引

  • is_monotonic: 如果索引序列递增则返回True

  • is_unique: 如果索引序列唯一则返回True

  • unique

基本功能

重建索引

In [8]:
obj = pd.Series([4.5, 7.2, -5.3, 3.6], index = ['d','b','a','c'])
obj
Out[8]:
d    4.5
b    7.2
a   -5.3
c    3.6
dtype: float64
In [9]:
obj2 = obj.reindex(['a','b','c','d','e'])
obj2
Out[9]:
a   -5.3
b    7.2
c    3.6
d    4.5
e    NaN
dtype: float64

对于顺序数据,比如时间序列,在重建索引时可能会需要进行插值或填值。method可选参数允许我们使用诸如ffill等方法在重建索引时插值,ffill是前向填充

In [11]:
obj3 = pd.Series(['blue','purple','yellow'], index=[0,2,4])
obj3
Out[11]:
0      blue
2    purple
4    yellow
dtype: object
In [13]:
obj3.reindex(np.arange(6), method = 'ffill')
obj3
Out[13]:
0      blue
2    purple
4    yellow
dtype: object

在DataFrame中,reindex可以改变行索引、列索引,也可以同时改变。当仅传入一个序列时,结果中的行会重建索引

In [3]:
import pandas as pd
import numpy as np
frame = pd.DataFrame(np.arange(9).reshape((3,3)),
                    index = ['a','b','c'],
                    columns = ['Ohio','Texas','California'])
frame
Out[3]:
Ohio Texas California
a 0 1 2
b 3 4 5
c 6 7 8
In [15]:
frame2 = frame.reindex(['a','b','c','d'])
frame2
Out[15]:
Ohio Texas California
a 0.0 1.0 2.0
b 3.0 4.0 5.0
c 6.0 7.0 8.0
d NaN NaN NaN
In [4]:
# 列可以使用columns关键字重建索引
states = ['Texas','Utah','California']
frame.reindex(columns=states)
Out[4]:
Texas Utah California
a 1 NaN 2
b 4 NaN 5
c 7 NaN 8
In [5]:
# 使用loc进行更为简洁的标签索引
frame.loc[['a','b','c','d'],states]
/home/swami/anaconda3/lib/python3.7/site-packages/pandas/core/indexing.py:1494: FutureWarning: 
Passing list-likes to .loc or [] with any missing label will raise
KeyError in the future, you can use .reindex() as an alternative.

See the documentation here:
https://pandas.pydata.org/pandas-docs/stable/indexing.html#deprecate-loc-reindex-listlike
  return self._getitem_tuple(key)
Out[5]:
Texas Utah California
a 1.0 NaN 2.0
b 4.0 NaN 5.0
c 7.0 NaN 8.0
d NaN NaN NaN

轴向上删除条目

如果已经拥有索引数组或不含条目的列表,在轴向上删除一个或更多的条目就非常容易,但这样需要一些数据操作和集合逻辑,drop方法会返回一个含有指示值或轴向上删除值的新对象

In [6]:
obj = pd.Series(np.arange(5), index = ['a','b','c','d','e'])
obj
Out[6]:
a    0
b    1
c    2
d    3
e    4
dtype: int64
In [7]:
new_obj = obj.drop('c')
new_obj
Out[7]:
a    0
b    1
d    3
e    4
dtype: int64
In [8]:
obj
Out[8]:
a    0
b    1
c    2
d    3
e    4
dtype: int64
In [9]:
obj.drop(['d','c'])
Out[9]:
a    0
b    1
e    4
dtype: int64
In [10]:
# 在DataFrame中,索引值可以从轴向上删除。
data = pd.DataFrame(np.arange(16).reshape((4,4)),
                   index = ['Ohio','Colorado','Utah','New York'],
                   columns = ['one','two','three','four'])
data
Out[10]:
one two three four
Ohio 0 1 2 3
Colorado 4 5 6 7
Utah 8 9 10 11
New York 12 13 14 15
In [11]:
# 在调用drop时使用标签序列会根据行标签删除值(轴0)
data.drop(['Colorado','Ohio'])
Out[11]:
one two three four
Utah 8 9 10 11
New York 12 13 14 15
In [12]:
# 可以通过传递axis=1或axis='columns'来从列中删除值
data.drop('two',axis=1)
Out[12]:
one three four
Ohio 0 2 3
Colorado 4 6 7
Utah 8 10 11
New York 12 14 15
In [13]:
data.drop(['two','four'], axis='columns')
Out[13]:
one three
Ohio 0 2
Colorado 4 6
Utah 8 10
New York 12 14
In [14]:
# 直接操作原对象
obj.drop('c',inplace=True)
obj
Out[14]:
a    0
b    1
d    3
e    4
dtype: int64

索引、选择与过滤

Series的索引(obj[...])与NumPy数组索引的功能类似,只不过Series的索引值可以不仅仅是整数

In [15]:
obj = pd.Series(np.arange(4), index = ['a','b','c','d'])
obj
Out[15]:
a    0
b    1
c    2
d    3
dtype: int64
In [16]:
obj['b']
Out[16]:
1
In [17]:
obj[1]
Out[17]:
1
In [18]:
obj[2:4]
Out[18]:
c    2
d    3
dtype: int64
In [19]:
obj[['b','a','d']]
Out[19]:
b    1
a    0
d    3
dtype: int64
In [20]:
obj[[1,3]]
Out[20]:
b    1
d    3
dtype: int64
In [21]:
obj[obj < 2]
Out[21]:
a    0
b    1
dtype: int64
In [22]:
obj['b':'c']
Out[22]:
b    1
c    2
dtype: int64
In [23]:
obj['b':'c'] = 5
In [24]:
obj
Out[24]:
a    0
b    5
c    5
d    3
dtype: int64
In [25]:
data
Out[25]:
one two three four
Ohio 0 1 2 3
Colorado 4 5 6 7
Utah 8 9 10 11
New York 12 13 14 15
In [37]:
data['two']
Out[37]:
Ohio         0
Colorado     5
Utah         9
New York    13
Name: two, dtype: int64
In [44]:
data.two
Out[44]:
Ohio         0
Colorado     5
Utah         9
New York    13
Name: two, dtype: int64
In [46]:
data.loc[:, 'two']
Out[46]:
Ohio         0
Colorado     5
Utah         9
New York    13
Name: two, dtype: int64
In [28]:
data.loc['Ohio']
Out[28]:
one      0
two      1
three    2
four     3
Name: Ohio, dtype: int64
In [29]:
data.loc['Ohio','two'] #同时选择行和列中的一部分
Out[29]:
1
In [30]:
data[['three','one']]
Out[30]:
three one
Ohio 2 0
Colorado 6 4
Utah 10 8
New York 14 12
In [31]:
data[:2]
Out[31]:
one two three four
Ohio 0 1 2 3
Colorado 4 5 6 7
In [32]:
data[data['three'] > 5]
Out[32]:
one two three four
Colorado 4 5 6 7
Utah 8 9 10 11
New York 12 13 14 15
In [33]:
data < 5
Out[33]:
one two three four
Ohio True True True True
Colorado True False False False
Utah False False False False
New York False False False False
In [34]:
data[data < 5] = 0
data
Out[34]:
one two three four
Ohio 0 0 0 0
Colorado 0 5 6 7
Utah 8 9 10 11
New York 12 13 14 15
In [35]:
### 使用轴标签loc和iloc选择数据
data.loc['Colorado', ['two', 'three']]
Out[35]:
two      5
three    6
Name: Colorado, dtype: int64
In [38]:
data.iloc[2]
Out[38]:
one       8
two       9
three    10
four     11
Name: Utah, dtype: int64
In [47]:
data.iloc[:, 2]
Out[47]:
Ohio         0
Colorado     6
Utah        10
New York    14
Name: three, dtype: int64
In [39]:
data.iloc[2, [3,0,1]]
Out[39]:
four    11
one      8
two      9
Name: Utah, dtype: int64
In [40]:
data.iloc[[1,2],[3,0,1]]
Out[40]:
four one two
Colorado 7 0 5
Utah 11 8 9
In [41]:
data.loc[:'Utah','two']
Out[41]:
Ohio        0
Colorado    5
Utah        9
Name: two, dtype: int64
In [42]:
data.iloc[:,:3][data.three > 5]
Out[42]:
one two three
Colorado 0 5 6
Utah 8 9 10
New York 12 13 14
In [43]:
 
Out[43]:
Ohio         0
Colorado     0
Utah         8
New York    12
Name: one, dtype: int64

算术和数据对齐

不同索引的对象之间的算术行为是pandas提供给一些应用的一项重要特性。当你将对象相加时,如果存在某个索引对不相同,则返回结果的索引将是索引对的并集。对数据库用户来说,这个特性类似于索引标签的自动外链接(outer join)

In [2]:
s1 = pd.Series([7.3, -2.5, 3.4, 1.5], index = ['a','c','d','e'])
s2 = pd.Series([-2.1, 3.6, -1.5, 4, 3.1],
              index = ['a','c','e','f','g'])
s1
Out[2]:
a    7.3
c   -2.5
d    3.4
e    1.5
dtype: float64
In [3]:
s2
Out[3]:
a   -2.1
c    3.6
e   -1.5
f    4.0
g    3.1
dtype: float64
In [4]:
s1 + s2
Out[4]:
a    5.2
c    1.1
d    NaN
e    0.0
f    NaN
g    NaN
dtype: float64
In [5]:
df1 = pd.DataFrame(np.arange(9.).reshape((3,3)), 
                  columns = list('bcd'),
                  index = ['Ohio','Texas','Colorado'])
df2 = pd.DataFrame(np.arange(12.).reshape((4,3)),
                  columns = list('bde'),
                  index = ['Utah','Ohio','Texas','Oregon'])
df1
Out[5]:
b c d
Ohio 0.0 1.0 2.0
Texas 3.0 4.0 5.0
Colorado 6.0 7.0 8.0
In [6]:
df2
Out[6]:
b d e
Utah 0.0 1.0 2.0
Ohio 3.0 4.0 5.0
Texas 6.0 7.0 8.0
Oregon 9.0 10.0 11.0
In [7]:
df1 + df2
Out[7]:
b c d e
Colorado NaN NaN NaN NaN
Ohio 3.0 NaN 6.0 NaN
Oregon NaN NaN NaN NaN
Texas 9.0 NaN 12.0 NaN
Utah NaN NaN NaN NaN
In [8]:
# 如果将两个行或列完全不同的DataFrame对象相加,结果将全部为空
df1 = pd.DataFrame({'A':[1,2]})
df2 = pd.DataFrame({'B':[3,4]})
df1
Out[8]:
A
0 1
1 2
In [9]:
df2
Out[9]:
B
0 3
1 4
In [10]:
df1 - df2
Out[10]:
A B
0 NaN NaN
1 NaN NaN
In [11]:
df1 = pd.DataFrame(np.arange(12.).reshape((3,4)),
                  columns = list('abcd'))
df2 = pd.DataFrame(np.arange(20.).reshape((4,5)),
                  columns = list('abcde'))
df2.loc[1,'b'] = np.nan
In [12]:
df1
Out[12]:
a b c d
0 0.0 1.0 2.0 3.0
1 4.0 5.0 6.0 7.0
2 8.0 9.0 10.0 11.0
In [13]:
df2
Out[13]:
a b c d e
0 0.0 1.0 2.0 3.0 4.0
1 5.0 NaN 7.0 8.0 9.0
2 10.0 11.0 12.0 13.0 14.0
3 15.0 16.0 17.0 18.0 19.0
In [14]:
# 将这些df添加到一起会导致在一些不重叠的位置出现NA
df1 + df2
Out[14]:
a b c d e
0 0.0 2.0 4.0 6.0 NaN
1 9.0 NaN 13.0 15.0 NaN
2 18.0 20.0 22.0 24.0 NaN
3 NaN NaN NaN NaN NaN
In [15]:
df1.add(df2, fill_value=0)
Out[15]:
a b c d e
0 0.0 2.0 4.0 6.0 4.0
1 9.0 5.0 13.0 15.0 9.0
2 18.0 20.0 22.0 24.0 14.0
3 15.0 16.0 17.0 18.0 19.0
In [17]:
df1.reindex(columns = df2.columns, fill_value = 0)
Out[17]:
a b c d e
0 0.0 1.0 2.0 3.0 0
1 4.0 5.0 6.0 7.0 0
2 8.0 9.0 10.0 11.0 0

算术方法

  • add, radd

  • sub, rsub

  • div, rdiv

  • floordiv, rfloordiv

  • mul, rmul

  • pow, rpow

In [18]:
frame = pd.DataFrame(np.arange(12.).reshape((4,3)),
                    columns=list('bde'),
                    index=['Utah','Ohio','Texas','Oregon'])
series = frame.iloc[0]
In [19]:
frame
Out[19]:
b d e
Utah 0.0 1.0 2.0
Ohio 3.0 4.0 5.0
Texas 6.0 7.0 8.0
Oregon 9.0 10.0 11.0
In [20]:
series
Out[20]:
b    0.0
d    1.0
e    2.0
Name: Utah, dtype: float64
In [21]:
frame - series
Out[21]:
b d e
Utah 0.0 0.0 0.0
Ohio 3.0 3.0 3.0
Texas 6.0 6.0 6.0
Oregon 9.0 9.0 9.0
In [22]:
series2 = pd.Series(range(3), index = ['b','e','f'])
frame + series2
Out[22]:
b d e f
Utah 0.0 NaN 3.0 NaN
Ohio 3.0 NaN 6.0 NaN
Texas 6.0 NaN 9.0 NaN
Oregon 9.0 NaN 12.0 NaN

函数应用和映射

In [23]:
frame = pd.DataFrame(np.random.randn(4,3),
                    columns=list('bde'),
                    index=['Utah','Ohio','Texas','Oregon'])
frame
Out[23]:
b d e
Utah 1.671802 0.148099 -1.042129
Ohio 1.836078 -1.049351 1.290140
Texas -0.965694 2.520744 1.252602
Oregon 0.859382 1.590559 -0.756151
In [24]:
np.abs(frame)
Out[24]:
b d e
Utah 1.671802 0.148099 1.042129
Ohio 1.836078 1.049351 1.290140
Texas 0.965694 2.520744 1.252602
Oregon 0.859382 1.590559 0.756151

另一个常用的操作是用apply将函数应用到一行或一列的一维数组上。

In [25]:
f = lambda x: x.max() - x.min()
frame.apply(f)
Out[25]:
b    2.801771
d    3.570095
e    2.332269
dtype: float64
In [26]:
frame.apply(f, axis = 'columns')
Out[26]:
Utah      2.713931
Ohio      2.885429
Texas     3.486437
Oregon    2.346710
dtype: float64
In [27]:
# 传递给apply的函数并不一定要返回一个标量值,也可以返回带有多个值的Series
def f(x):
    return pd.Series([x.min(), x.max()], index = ['min','max'])
In [28]:
frame.apply(f)
Out[28]:
b d e
min -0.965694 -1.049351 -1.042129
max 1.836078 2.520744 1.290140

逐元素的Python函数也可以使用,假设想要根据frame中的每个浮点数计算一个格式化字符串,可以使用applymap方法

In [29]:
format = lambda x: '%.2f' %x
frame.applymap(format)
Out[29]:
b d e
Utah 1.67 0.15 -1.04
Ohio 1.84 -1.05 1.29
Texas -0.97 2.52 1.25
Oregon 0.86 1.59 -0.76
In [30]:
# 使用applymap作为函数名是因为Series有map方法,可以将逐元素函数应用到Series上
frame['e'].map(format)
Out[30]:
Utah      -1.04
Ohio       1.29
Texas      1.25
Oregon    -0.76
Name: e, dtype: object

排序和排名

In [31]:
obj = pd.Series(range(4), index = ['d','a','b','c'])
obj.sort_index()
Out[31]:
a    1
b    2
c    3
d    0
dtype: int64
In [32]:
# 在DataFrame中,可以在各个轴上按索引排序
frame = pd.DataFrame(np.arange(8).reshape((2,4)),
                    index = ['three','one'],
                    columns = ['d','a','b','c'])
frame.sort_index()
Out[32]:
d a b c
one 4 5 6 7
three 0 1 2 3
In [34]:
frame.sort_index(axis = 1, ascending = False)
Out[34]:
d c b a
three 0 3 2 1
one 4 7 6 5
In [35]:
# 如果要对Series的值进行排序,使用sort_values方法:
obj = pd.Series([4,7,-3,2])
obj.sort_values()
Out[35]:
2   -3
3    2
0    4
1    7
dtype: int64
In [36]:
# 当对DataFrame排序时,可以使用一列或多列作为排序键:
frame = pd.DataFrame({'b':[4,7,-3,2],'a':[0,1,0,1]})
frame
Out[36]:
b a
0 4 0
1 7 1
2 -3 0
3 2 1
In [37]:
frame.sort_values(by = 'b')
Out[37]:
b a
2 -3 0
3 2 1
0 4 0
1 7 1
In [38]:
frame.sort_values(by = ['a','b'])
Out[38]:
b a
2 -3 0
0 4 0
3 2 1
1 7 1
In [39]:
# Series和DataFrame的rank方法实现排名,默认情况下rank通过将平均排名分配到每个组来打破平级关系
obj = pd.Series([7, -5, 7, 4, 2, 0,4])
obj.rank()
Out[39]:
0    6.5
1    1.0
2    6.5
3    4.5
4    3.0
5    2.0
6    4.5
dtype: float64
In [40]:
# 排名也可以根据他们在数据中的观察顺序进行分配
obj.rank(method= 'first')
Out[40]:
0    6.0
1    1.0
2    7.0
3    4.0
4    3.0
5    2.0
6    5.0
dtype: float64
In [41]:
# 按降序排名,将值分配给组中的最大排名
obj.rank(ascending = False, method='max')
Out[41]:
0    2.0
1    7.0
2    2.0
3    4.0
4    5.0
5    6.0
6    4.0
dtype: float64
In [42]:
frame = pd.DataFrame({'b':[4.3,7,-3,2],'a':[0,1,0,1],'c':[-2,5,8,-2.5]})
frame
Out[42]:
b a c
0 4.3 0 -2.0
1 7.0 1 5.0
2 -3.0 0 8.0
3 2.0 1 -2.5
In [43]:
frame.rank(axis='columns')
Out[43]:
b a c
0 3.0 2.0 1.0
1 3.0 1.0 2.0
2 1.0 2.0 3.0
3 3.0 2.0 1.0

排名中平级关系打破方法

  • average: 默认,在每个组中分配平均排名

  • min: 对整个组使用最小排名

  • max: 对整个组使用最大排名

  • first: 按照值在数据中出现的次序分配排名

  • dense: 类似于method='min',但组间排名总是增加1,而不是一个组中的相等元素的数量

描述性统计的概述与计算

In [44]:
df = pd.DataFrame([[1.4,np.nan],[7.1,-4.5],
                  [np.nan, np.nan],[0.75, -1.3]],
                 index=['a','b','c','d'],
                 columns=['one','two'])
df
Out[44]:
one two
a 1.40 NaN
b 7.10 -4.5
c NaN NaN
d 0.75 -1.3
In [45]:
df.sum()
Out[45]:
one    9.25
two   -5.80
dtype: float64
In [46]:
df.sum(axis=1)
Out[46]:
a    1.40
b    2.60
c    0.00
d   -0.55
dtype: float64
In [47]:
df.sum(axis="columns")
Out[47]:
a    1.40
b    2.60
c    0.00
d   -0.55
dtype: float64
In [48]:
# 除非整个切片(在本例中是行或列)都是NA,否则NA值是被自动排除的。可以通过禁用skipna来实现不排除NA值
df.mean(axis="columns",skipna=False)
Out[48]:
a      NaN
b    1.300
c      NaN
d   -0.275
dtype: float64
In [49]:
# idxmin和idxmax,返回的是间接统计信息,比如最小值或最大值所在的索引标签
df.idxmax()
Out[49]:
one    b
two    d
dtype: object
In [50]:
df.idxmin()
Out[50]:
one    d
two    b
dtype: object
In [51]:
df.cumsum()
Out[51]:
one two
a 1.40 NaN
b 8.50 -4.5
c NaN NaN
d 9.25 -5.8
In [52]:
df.describe()
Out[52]:
one two
count 3.000000 2.000000
mean 3.083333 -2.900000
std 3.493685 2.262742
min 0.750000 -4.500000
25% 1.075000 -3.700000
50% 1.400000 -2.900000
75% 4.250000 -2.100000
max 7.100000 -1.300000
In [53]:
# 对于非数值型数据,describe产生另一种汇总统计
obj = pd.Series(['a','a','b','c'] * 4)
obj.describe()
Out[53]:
count     16
unique     3
top        a
freq       8
dtype: object

描述性统计和汇总统计

  • count: 非NA值的个数

  • describe: 计算Series或DataFrame各列的汇总统计集合

  • min, max

  • argmin, argmax

  • idxmin, idxmax

  • quantile: 计算样本从0到1间的分位数

  • sum

  • mean

  • median

  • mad: 平均值的平均绝对偏差

  • prod: 所有值的积

  • var: 值的样本方差

  • std: 标准差

  • skew: 偏度

  • kurt: 峰度

  • cumsum

  • cummin, cummax

  • cumprod

  • diff

  • pct_change: 计算百分比

唯一值、计数和成员属性

In [7]:
obj = pd.Series(['c','a','d','a','a','b','b','c','c'])
uniques = obj.unique()
In [8]:
uniques
Out[8]:
array(['c', 'a', 'd', 'b'], dtype=object)

唯一值并不一定按照排序好的顺序返回,但是如果需要的话可以进行排序(uniques.sort())。相应的,value_counts()计算Series包含的值的个数

In [9]:
obj.value_counts()
Out[9]:
a    3
c    3
b    2
d    1
dtype: int64
In [10]:
# value_counts也是有效的pandas顶层方法,可以用于任意数组或序列
# 其返回一个Series,索引是唯一值序列,值是计数个数,按照个数降序排序
pd.value_counts(obj.values, sort=False)
Out[10]:
d    1
c    3
a    3
b    2
dtype: int64
In [11]:
# is执行向量化的成员属性检查,还可以将数据集以Series或DataFrame一列的形式过滤为数据集的值子集
obj
Out[11]:
0    c
1    a
2    d
3    a
4    a
5    b
6    b
7    c
8    c
dtype: object
In [12]:
mask=obj.isin(['b','c'])
mask
Out[12]:
0     True
1    False
2    False
3    False
4    False
5     True
6     True
7     True
8     True
dtype: bool
In [13]:
obj[mask]
Out[13]:
0    c
5    b
6    b
7    c
8    c
dtype: object

isin相关的Index.get_indexer方法,可以提供一个索引数组,这个索引数组可以将可能非唯一值数组转换为另一个唯一值数组

In [14]:
to_match = pd.Series(['c','a','b','b','c','a'])
unique_vals = pd.Series(['c','b','a'])
to_match
Out[14]:
0    c
1    a
2    b
3    b
4    c
5    a
dtype: object
In [15]:
pd.Index(unique_vals).get_indexer(to_match)
Out[15]:
array([0, 2, 1, 1, 0, 2])

唯一值、计数和集合成员属性方法

  • isin

  • match: 计算数组中每个值的整数索引,形成一个唯一值数组。有助于数据对齐和join类型的操作

  • unique

  • value_counts

In [17]:
data = pd.DataFrame({'Qu1':[1,3,4,3,4],
                    'Qu2':[2,3,1,2,3],
                    'Qu3':[1,5,2,4,4]})
data
Out[17]:
Qu1 Qu2 Qu3
0 1 2 1
1 3 3 5
2 4 1 2
3 3 2 4
4 4 3 4
In [19]:
result = data.apply(pd.value_counts).fillna(0)
# 结果中行标签是所有列中出现的不同值,数值则是这些不同值在每个列中出现的次数
result
Out[19]:
Qu1 Qu2 Qu3
1 1.0 1.0 1.0
2 0.0 2.0 1.0
3 2.0 2.0 0.0
4 2.0 0.0 2.0
5 0.0 0.0 1.0
In [ ]: