Series

创建

Series是一种类似于一维数组的对象,它由一组数据(各种NumPy数据类型)以及一组与之相关的数据标签(即索引)组成。仅由一组数据即可产生最简单的Series

  1. In [1]: import pandas as pd
  2. In [2]: obj = pd.Series([4, 7, -5, 3])
  3. In [3]: obj
  4. Out[3]:
  5. 0 4
  6. 1 7
  7. 2 -5
  8. 3 3
  9. dtype: int64

Series的字符串表现形式为:索引在左边,值在右边。由于我们没有为数据指定索引,于是会自动创建一个0到N-1(N为数据的长度)的整数型索引。你可以通过Series的 valuesindex 属性获取其数组表示形式和索引对象

  1. In [4]: obj.values
  2. Out[4]: array([ 4, 7, -5, 3], dtype=int64)
  3. In [6]: obj.index
  4. Out[6]: RangeIndex(start=0, stop=4, step=1)

可以看出, pandas中的区间也是左开右闭的, 这跟NumPy是一致的

索引

通常,我们希望所创建的Series带有一个可以对各个数据点进行标记的索引

  1. In [7]: obj2 = pd.Series([4, 7, -5, 3], index=['b', 'd', 'a', 'c'])
  2. In [8]: obj2
  3. Out[8]:
  4. b 4
  5. d 7
  6. a -5
  7. c 3
  8. dtype: int64
  9. In [9]: obj2.index
  10. Out[9]: Index(['b', 'd', 'a', 'c'], dtype='object')

与普通NumPy数组相比,可以通过索引的方式选取Series中的单个或一组值

  1. In [10]: obj2['a']
  2. Out[10]: -5
  3. In [11]: obj2['d'] = 6
  4. In [12]: obj2[['c', 'a', 'b']]
  5. Out[12]:
  6. c 3
  7. a -5
  8. b 4
  9. dtype: int64

[‘c’, ‘a’, ‘d’]是索引列表,即使它包含的是字符串而不是整数

运算

使用NumPy函数或类似NumPy的运算(如根据布尔型数组进行过滤、标量乘法、应用数学函数等)都会保留索引值的链接

  1. In [13]: obj2[obj2 > 0]
  2. Out[13]:
  3. b 4
  4. d 6
  5. c 3
  6. dtype: int64
  7. In [14]: obj2 * 2
  8. Out[14]:
  9. b 8
  10. d 12
  11. a -10
  12. c 6
  13. dtype: int64
  14. In [15]: import numpy as np
  15. In [16]: np.exp(obj2)
  16. Out[16]:
  17. b 54.598150
  18. d 403.428793
  19. a 0.006738
  20. c 20.085537
  21. dtype: float64

可看作字典

还可以将Series看成是一个定长的有序字典,因为它是索引值到数据值的一个映射。它可以用在许多原本需要字典参数的函数中

  1. In [17]: 'b' in obj2
  2. Out[17]: True
  3. In [18]: 'e' in obj2
  4. Out[18]: False

如果数据被存放在一个Python字典中,也可以直接通过这个字典来创建Series

  1. In [20]: sdata = {'Ohio': 2223, 'Twxa': 30002, 'Oregon': 17002, 'Utah': 23144}
  2. In [21]: obj3 = pd.Series(sdata)
  3. In [22]: obj3
  4. Out[22]:
  5. Ohio 2223
  6. Twxa 30002
  7. Oregon 17002
  8. Utah 23144
  9. dtype: int64

如果只传入一个字典,则结果Series中的索引就是原字典的键(有序排列)。你可以传入排好序的字典的键以改变顺序

  1. In [23]: states = ['California', 'Ohio', 'Oregon', 'Texas']
  2. In [24]: obj4 = pd.Series(sdata, index=states)
  3. In [26]: obj4
  4. Out[26]:
  5. California NaN
  6. Ohio 2223.0
  7. Oregon 17002.0
  8. Texas NaN
  9. dtype: float64

在这个例子中, sdata 中跟states 索引相匹配的那3个值会被找出来并放到相应的位置上, 但由于”California”所对应的sdata值找不到,所以其结果就为NaN(即“非数字”(not a number),在pandas中, 它用于表示缺失或NA值)。因为‘Utah’不在states 中,它被从结果中除去
我将使用缺失(missing)或NA表示缺失数据。pandasisnullnotnull 函数可用于检测缺失数据

  1. In [27]: pd.isnull(obj4)
  2. Out[27]:
  3. California True
  4. Ohio False
  5. Oregon False
  6. Texas True
  7. dtype: bool
  8. In [28]: pd.notnull(obj4)
  9. Out[28]:
  10. California False
  11. Ohio True
  12. Oregon True
  13. Texas False
  14. dtype: bool

Series也有类似的实例方法

  1. In [29]: obj4.isnull()
  2. Out[29]:
  3. California True
  4. Ohio False
  5. Oregon False
  6. Texas True
  7. dtype: bool

对于许多应用而言,Series最重要的一个功能是,它会根据运算的索引标签自动对齐数据, 这类似于数据库中的join操作

  1. In [30]: obj3
  2. Out[30]:
  3. Ohio 2223
  4. Twxa 30002
  5. Oregon 17002
  6. Utah 23144
  7. dtype: int64
  8. In [31]: obj4
  9. Out[31]:
  10. California NaN
  11. Ohio 2223.0
  12. Oregon 17002.0
  13. Texas NaN
  14. dtype: float64
  15. In [32]: obj3 + obj4
  16. Out[32]:
  17. California NaN
  18. Ohio 4446.0
  19. Oregon 34004.0
  20. Texas NaN
  21. Twxa NaN
  22. Utah NaN
  23. dtype: float64

Series对象本身及其索引都有一个name属性,该属性跟pandas其他的关键功能关系非常密切

  1. In [5]: obj4.name = 'population'
  2. In [6]: obj4.index.name = 'state'
  3. In [7]: obj4
  4. Out[7]:
  5. state
  6. California NaN
  7. Oiho NaN
  8. Oregon 16000.0
  9. Texas 71000.0
  10. Name: population, dtype: float64

Series的索引可以通过赋值的方式就地修改

  1. In [8]: obj4.index = [1,2,3,4]
  2. In [9]: obj4
  3. Out[9]:
  4. 1 NaN
  5. 2 NaN
  6. 3 16000.0
  7. 4 71000.0
  8. Name: population, dtype: float64

DataFrame

DataFrame是一个表格型的数据结构,它含有一组有序的列,每列可以是不同的值类型(数值、字符串、布尔值等)。DataFrame既有行索引也有列索引,它可以被看做由Series组成的字典(共用同一个索引)。DataFrame中的数据是以一个或多个二维块存放的(而不是列表、字典或别的一维数据结构)

创建

DataFrame的办法有很多, 最常用的一种是直接传入一个由等长列表或NumPy数组组成的字典

  1. In [10]: data = {'state': ['Ohio', 'Ohio', 'Ohio', 'Nevada', 'Nevada', 'Nevada'],
  2. ...: 'year': [2000, 2001, 2002, 2001, 2002, 2003],
  3. ...: 'pop': [1.5, 1.7, 3.6, 2.4, 2.9, 3.2]}
  4. In [11]: frame = pd.DataFrame(data)
  5. In [12]: frame
  6. Out[12]:
  7. state year pop
  8. 0 Ohio 2000 1.5
  9. 1 Ohio 2001 1.7
  10. 2 Ohio 2002 3.6
  11. 3 Nevada 2001 2.4
  12. 4 Nevada 2002 2.9
  13. 5 Nevada 2003 3.2

对于特别大的DataFramehead 方法会选取前五行

  1. In [13]: frame.head()
  2. Out[13]:
  3. state year pop
  4. 0 Ohio 2000 1.5
  5. 1 Ohio 2001 1.7
  6. 2 Ohio 2002 3.6
  7. 3 Nevada 2001 2.4
  8. 4 Nevada 2002 2.9

指定列名

如果指定了列序列,则DataFrame的列就会按照指定顺序进行排列

  1. In [14]: pd.DataFrame(data, columns=['year', 'state', 'pop'])
  2. Out[14]:
  3. year state pop
  4. 0 2000 Ohio 1.5
  5. 1 2001 Ohio 1.7
  6. 2 2002 Ohio 3.6
  7. 3 2001 Nevada 2.4
  8. 4 2002 Nevada 2.9
  9. 5 2003 Nevada 3.2

如果传入的列在数据中找不到, 就会在结果中产生缺失值

  1. In [16]: frame2 = pd.DataFrame(data, columns=['year', 'state', 'pop', 'debt'],
  2. ...: index=['one', 'two', 'three', 'four', 'five',
  3. ...: 'six'])
  4. In [17]: frame2
  5. Out[17]:
  6. year state pop debt
  7. one 2000 Ohio 1.5 NaN
  8. two 2001 Ohio 1.7 NaN
  9. three 2002 Ohio 3.6 NaN
  10. four 2001 Nevada 2.4 NaN
  11. five 2002 Nevada 2.9 NaN
  12. six 2003 Nevada 3.2 NaN
  13. In [19]: frame2.columns
  14. Out[19]: Index(['year', 'state', 'pop', 'debt'], dtype='object')

索引

通过类似字典标记的方式或属性的方式,可以将DataFrame的列获取为一个Series

  1. In [20]: frame2['state']
  2. Out[20]:
  3. one Ohio
  4. two Ohio
  5. three Ohio
  6. four Nevada
  7. five Nevada
  8. six Nevada
  9. Name: state, dtype: object
  10. In [21]: frame2.year
  11. Out[21]:
  12. one 2000
  13. two 2001
  14. three 2002
  15. four 2001
  16. five 2002
  17. six 2003
  18. Name: year, dtype: int64

笔记: IPython提供了类似属性的访问(即frame2.year) 和tab补全。 frame2[column]适用于任何列的名, 但是frame2.column只有在列名是一个合理的Python变量名时才适用

注意,返回的Series拥有原DataFrame相同的索引,且其 name 属性也已经被相应地设置好了。行也可以通过位置或名称的方式进行获取, 比如用 loc 属性

  1. In [22]: frame2.loc['three']
  2. Out[22]:
  3. year 2002
  4. state Ohio
  5. pop 3.6
  6. debt NaN
  7. Name: three, dtype: object

列可以通过赋值的方式进行修改。例如,我们可以给那个空的”debt“列赋上一个标量值或一组值

  1. In [23]: frame2['debt'] = 16.5
  2. In [24]: frame2
  3. Out[24]:
  4. year state pop debt
  5. one 2000 Ohio 1.5 16.5
  6. two 2001 Ohio 1.7 16.5
  7. three 2002 Ohio 3.6 16.5
  8. four 2001 Nevada 2.4 16.5
  9. five 2002 Nevada 2.9 16.5
  10. six 2003 Nevada 3.2 16.5
  11. In [25]: import numpy as np
  12. In [26]: frame2['debt'] = np.arange(6.)
  13. In [27]: frame2
  14. Out[27]:
  15. year state pop debt
  16. one 2000 Ohio 1.5 0.0
  17. two 2001 Ohio 1.7 1.0
  18. three 2002 Ohio 3.6 2.0
  19. four 2001 Nevada 2.4 3.0
  20. five 2002 Nevada 2.9 4.0
  21. six 2003 Nevada 3.2 5.0

将列表或数组赋值给某个列时,其长度必须跟DataFrame的长度相匹配。如果赋值的是一个Series,就会精确匹配DataFrame的索引,所有的空位都将被填上缺失值

  1. In [28]: val = pd.Series([-1.2, -1.5, -1.7], index=['two', 'four', 'five'])
  2. In [29]: frame2['debt'] = val
  3. In [30]: frame2
  4. Out[30]:
  5. year state pop debt
  6. one 2000 Ohio 1.5 NaN
  7. two 2001 Ohio 1.7 -1.2
  8. three 2002 Ohio 3.6 NaN
  9. four 2001 Nevada 2.4 -1.5
  10. five 2002 Nevada 2.9 -1.7
  11. six 2003 Nevada 3.2 NaN

删除列

为不存在的列赋值会创建出一个新列。关键字 del 用于删除列

  1. In [31]: frame2['eastern'] = frame2.state == 'Ohio'
  2. In [32]: frame2
  3. Out[32]:
  4. year state pop debt eastern
  5. one 2000 Ohio 1.5 NaN True
  6. two 2001 Ohio 1.7 -1.2 True
  7. three 2002 Ohio 3.6 NaN True
  8. four 2001 Nevada 2.4 -1.5 False
  9. five 2002 Nevada 2.9 -1.7 False
  10. six 2003 Nevada 3.2 NaN False
  11. In [33]: del frame2['eastern']
  12. In [34]: frame2.columns
  13. Out[34]: Index(['year', 'state', 'pop', 'debt'], dtype='object')

注意: 通过索引方式返回的列只是相应数据的视图而已, 并不是副本。 因此, 对返回的Series所做的任何就地修改全都会反映到源DataFrame上。 通过Series的copy方法即可指定复制列

嵌套字典初始化

另一种常见的数据形式是嵌套字典。如果嵌套字典传给DataFramepandas就会被解释为:外层字典的键作为列,内层键则作为行索引

  1. In [35]: pop = {'Nevada': {2001: 2.4, 2002: 2.9},
  2. ...: 'Ohio': {2000: 1.5, 2001: 1.7, 2002: 3.6}}
  3. In [36]: frame3 = pd.DataFrame(pop)
  4. In [37]: frame3
  5. Out[37]:
  6. Nevada Ohio
  7. 2001 2.4 1.7
  8. 2002 2.9 3.6
  9. 2000 NaN 1.5

你也可以使用类似NumPy数组的方法,对DataFrame进行转置

  1. In [38]: frame.T
  2. Out[38]:
  3. 0 1 2 3 4 5
  4. state Ohio Ohio Ohio Nevada Nevada Nevada
  5. year 2000 2001 2002 2001 2002 2003
  6. pop 1.5 1.7 3.6 2.4 2.9 3.2

内层字典的键会被合并、排序以形成最终的索引。如果明确指定了索引,则不会这样

  1. In [39]: pd.DataFrame(pop, index=[2001, 2002, 2003])
  2. Out[39]:
  3. Nevada Ohio
  4. 2001 2.4 1.7
  5. 2002 2.9 3.6
  6. 2003 NaN NaN

Series组成的字典差不多也是一样的用法

  1. In [40]: pdata = {'Ohio': frame3['Ohio'][:-1],
  2. ...: 'Nevada': frame3['Nevada'][:2]}
  3. In [41]: pd.DataFrame(pdata)
  4. Out[41]:
  5. Ohio Nevada
  6. 2001 1.7 2.4
  7. 2002 3.6 2.9

DataFrame构造函数所能接受的各种数据如下表
image.png
跟Series一样,values 属性也会以二维ndarray的形式返回DataFrame中的数据

  1. In [43]: frame3.values
  2. Out[43]:
  3. array([[2.4, 1.7],
  4. [2.9, 3.6],
  5. [nan, 1.5]])

如果DataFrame各列的数据类型不同,则值数组的dtype就会选用能兼容所有列的数据类型

  1. In [44]: frame2.values
  2. Out[44]:
  3. array([[2000, 'Ohio', 1.5, nan],
  4. [2001, 'Ohio', 1.7, -1.2],
  5. [2002, 'Ohio', 3.6, nan],
  6. [2001, 'Nevada', 2.4, -1.5],
  7. [2002, 'Nevada', 2.9, -1.7],
  8. [2003, 'Nevada', 3.2, nan]], dtype=object)

索引对象

pandas的索引对象负责管理轴标签和其他元数据(比如轴名称等)。构建 SeriesDataFrame 时, 所用到的任何数组或其他序列的标签都会被转换成一个 Index

  1. In [3]: obj = pd.Series(range(3), index=['a', 'b', 'c'])
  2. In [6]: index = obj.index
  3. In [7]: index[1:]
  4. Out[7]: Index(['b', 'c'], dtype='object')

Index 对象是不可变的,因此用户不能对其进行修改

  1. index[1] = 'd' # TypeError

不可变可以使 Index 对象在多个数据结构之间安全共享

  1. In [9]: labels = pd.Index(np.arange(3))
  2. In [10]: labels
  3. Out[10]: Int64Index([0, 1, 2], dtype='int64')
  4. In [11]: obj2 = pd.Series([1.5, 2.2, 3.1], index=labels)
  5. In [12]: obj2
  6. Out[12]:
  7. 0 1.5
  8. 1 2.2
  9. 2 3.1
  10. dtype: float64
  11. In [13]: obj2.index is labels
  12. Out[13]: True

注意:虽然用户不需要经常使用Index的功能,但是因为一些操作会生成包含被索引化的数据,理解它们的工作原理是很重要的

除了类似于数组, Index 的功能也类似一个固定大小的集合

  1. In [14]: frame3
  2. Out[14]:
  3. state Nevada Ohio
  4. year
  5. 2000 NaN 1.5
  6. 2001 2.4 1.7
  7. 2002 2.9 3.6
  8. In [15]: frame3.columns
  9. Out[15]: Index(['Nevada', 'Ohio'], dtype='object', name='state')
  10. In [16]: 'Ohio' in frame3.columns
  11. Out[16]: True
  12. In [17]: 2003 in frame3.index
  13. Out[17]: False

python的集合不同,pandasIndex 可以包含重复的标签

  1. In [14]: dup_labels = pd.Index(['foo', 'foo', 'bar', 'bar'])
  2. In [15]: dup_labels
  3. Out[15]: Index(['foo', 'foo', 'bar', 'bar'], dtype='object')

下表是每一个索引的方法和属性
image.png