2. pandas简单使用

pandas三个主要的数据结构是Series,DataFrame和Index,三个结构用来对数据进行操作。

本章主要介绍pandas三大件,让读者对pandas有个简单的了解:

  • Series
  • DataFrame
  • Index

2.1. pandas.Series对象

是一个带索引数据构成的一维数组。

Series给数组和一组索引绑定在一起,有点类似于list,但是Series的索引绑定的是显式索引。

如果想获取绑定的数据和索引内容,分别可以使用values属性和index属性。

2.1.1. Series的创建

岁Series对象的创建主要分为:

  • 使用数组直接创建,此时索引为默认索引
  • 使用数组创建,显式指定索引
  • 使用字典创建
# Series对象的创建
# 直接使用数组进行创建

import pandas as pd

data = pd.Series([10, 11, 12, 13,14])

print("完整Series内容是:\n", data)

print("\nSeries的值: \n\n", data.values)

print("\nSeries的索引是: \n", data.index)
完整Series内容是:
 0    10
1    11
2    12
3    13
4    14
dtype: int64

Series的值: 

 [10 11 12 13 14]

Series的索引是: 
 RangeIndex(start=0, stop=5, step=1)
# 显式制定索引

data_index = pd.Series([10,11,12,13,14], index=[1,2,3,4,5])

print("data_index: \n", data_index)
data_index: 
 1    10
2    11
3    12
4    13
5    14
dtype: int64
#使用字典进行创建

d = {"one":1, "two":2, "three":3, "four":4, "five":5}
d_s = pd.Series(d)
print(d_s)
one      1
two      2
three    3
four     4
five     5
dtype: int64
import pandas as pd
# 对于字典,可以通过index来显式筛选内容
# 注意索引

d = {4:"four", 5:"five", 1:"one", 3:"three", 2:"two"}
d_s = pd.Series(d,  index=[2,1,3])
print(d_s)
2      two
1      one
3    three
dtype: object

2.1.2. Series对象的简单使用

Series和Numpy的数组很像,他们的区别主要体现在索引上:

  • Numpy通过隐士索引来对数据进行操作
  • Series通过显式索引来将索引和数值关联

显式索引具有更强大的功能,你可以对其进行修改操作:

Series的values和indexs可以直接使用,查看。 请注意这俩的类型。

import pandas as pd

data = pd.Series([10,11,12,13,14], index=[1,2,3,9,5])

print("data.values=", data.values)
print(type(data.values))

print()
print("data.indexs=", data.index)
print(type(data.index))
data.values= [10 11 12 13 14]
<class 'numpy.ndarray'>

data.indexs= Int64Index([1, 2, 3, 9, 5], dtype='int64')
<class 'pandas.core.indexes.numeric.Int64Index'>
### 对于series的对象的访问,完全可以像数组那样使用

# 数据选择使用显式索引
print("第一个值是:", data[1])

# 隐式索引
print("\n 前三个值是:\n ", data[:9])
print("\n 前三个值是:\n ", data[:4])
第一个值是: 10

 前三个值是:
  1    10
2    11
3    12
9    13
5    14
dtype: int64

 前三个值是:
  1    10
2    11
3    12
9    13
dtype: int64
# 对于不按顺序排列的index同样可以
# 请注意下例data[:2]是到index=2的那个位置结束,并不是从0开始的下标直到2结束

data = pd.Series([10, 11, 12, 13, 14], index=[54, 32, 2, 1, 9])
print("不连续数字作为索引也是可以的:\n", data)

print("\n data3  =", data[32])

print("\n data[:1] = \n", data[:1])
不连续数字作为索引也是可以的:
 54    10
32    11
2     12
1     13
9     14
dtype: int64

 data3  = 11

 data[:1] = 
 54    10
dtype: int64
# 对于自定义index同样可以使用切片
# !!!注意此时切片的结束位置,结果是包含结束位置的值的!!!

d = {"one":1, "two":2, "three":3, "four":4, "five":5}
d_s = pd.Series(d)

print('d_s["four"] = ', d_s["four"])
print('d_s[":four"] = \n', d_s[:"four"])
d_s["four"] =  4
d_s[":four"] = 
 one      1
two      2
three    3
four     4
dtype: int64

对数据的选取,Series处理的并不是特别好,在对数据访问的时候,显式索引和隐士索引容易造成混淆。

为了应对这种混乱,Python为我们提供了三个索引器,用以清晰访问数据:

  • loc: 只使用显式索引, label based indexing
  • iloc:只使用隐士索引, positional indexing
  • ix:前两种索引的混合模式,主要用在DataFrame中, 不推荐

首先我们观察一下对Series的访问的显式索引和隐士索引的使用。

# Series对显式索引和隐式索引的使用

s = pd.Series([11,12,13,14,15], index=[3,5,7,9,1])
print("s = \n", s)

# Series对于单个内容的访问,采用的是显式索引
# s[1]表示的是显式索引 ”1“ 的内容
print("\n s[1]=", s[1])


# Series切片采用的是隐士所含,即默认是从下标0开始的升序索引
# s[1:3] 选中的内容是s[1] 和 s[2]
print("\n s[1:3] = \n", s[1:3])


s = pd.Series([1,2,3,4,5], index=["one", "two", "three", "four", "five"])
print("\n s=\n", s)


# 对于显式索引的切片, 是包含最后一位内容的
# 这一点跟隐士索引有很大区别
print('\n s["two": "four"]=', s["two":"four"])
s = 
 3    11
5    12
7    13
9    14
1    15
dtype: int64

 s[1]= 15

 s[1:3] = 
 5    12
7    13
dtype: int64

 s=
 one      1
two      2
three    3
four     4
five     5
dtype: int64

 s["two": "four"]= two      2
three    3
four     4
dtype: int64
# loc索引器表示切片和取值都是显式的,不使用隐式索引。

s = pd.Series([11,12,13,14,15], index=[3,5,7,9,1])
print("s = \n", s)

print("\n s.loc[3] = ", s.loc[3])
print("\n s.loc[3:9] = \n", s.loc[3:9])
s = 
 3    11
5    12
7    13
9    14
1    15
dtype: int64

 s.loc[3] =  11

 s.loc[3:9] = 
 3    11
5    12
7    13
9    14
dtype: int64
# iloc索引器表示切片和取值都是隐式的,不使用显式索引
s = pd.Series([11,12,13,14,15], index=[3,5,7,9,1])
print("s = \n", s)

print("\n s.iloc[3] = ", s.iloc[3])
print("\n s.iloc[3:9] = \n", s.iloc[3:9])
s = 
 3    11
5    12
7    13
9    14
1    15
dtype: int64

 s.iloc[3] =  14

 s.iloc[3:9] = 
 9    14
1    15
dtype: int64

2.2. pandas.DataFrame对象

  • DataFrame可以看做是通用的NumPy数组,也可以看做特殊的字典
  • DataFrame最常见的结构可以想象成一个Excel内容,每一行都有行号,每一列都有列名的二维结构

创建DataFrame的方式比较多,常见的有:

  • 通过单个Series创建
  • 通过字典列表创建
  • 通过Series对象字典创建
  • 通过NumPy二维数组创建
  • 通过Numpy结构化数组创建
# 通过单个Series对象创建

import pandas as pd

s = pd.Series([1,2,3,4,5])
print("S=\n", s)

print()
df = pd.DataFrame(s, columns=['digits'])
print("df=\n", df)
S=
 0    1
1    2
2    3
3    4
4    5
dtype: int64

df=
    digits
0       1
1       2
2       3
3       4
4       5
# 通过字典列表创建

dl = [{"个": i, "十":i*10, "百":i*100} for i in range(1,5)]
print("dl = ", dl)

df = pd.DataFrame(dl)
print("df = \n", df)


# 在通过字典创建的时候,如果有的值并不存在,则自动用NaN填充
# 参看下面例子
dl = [{"a":1, "b":1}, {"b":2, "c":2}, {"c":3, "d":3}]
df = pd.DataFrame(dl)
print("df = \n", df)
dl =  [{'个': 1, '十': 10, '百': 100}, {'个': 2, '十': 20, '百': 200}, {'个': 3, '十': 30, '百': 300}, {'个': 4, '十': 40, '百': 400}]
df = 
           
0  1  10  100
1  2  20  200
2  3  30  300
3  4  40  400
df = 
      a    b    c    d
0  1.0  1.0  NaN  NaN
1  NaN  2.0  2.0  NaN
2  NaN  NaN  3.0  3.0
# 通过Series对象字典创建

s1 = pd.Series([i for i in range(1,6)], index=[1,2,3,4,5])
s2 = pd.Series([i*10 for i in range(1,6)], index=[3,4,5,6,7])

df = pd.DataFrame({"个": s1, "十":s2})
print("df = \n", df)
df = 
           
1  1.0   NaN
2  2.0   NaN
3  3.0  10.0
4  4.0  20.0
5  5.0  30.0
6  NaN  40.0
7  NaN  50.0
# 通过Numpy二维数组创建
import numpy as np

df = pd.DataFrame(np.zeros([5,3]), 
                  columns=["A", "B", "C"], 
                 index=["one", "two", "three", "four", "five"])
print("df=\n",df)
df=
          A    B    C
one    0.0  0.0  0.0
two    0.0  0.0  0.0
three  0.0  0.0  0.0
four   0.0  0.0  0.0
five   0.0  0.0  0.0
import pandas as pd
import numpy as np
# 通过Numpy结构化数组

d = np.zeros(3, dtype=[("A", "i8"), ("B", "f8")])
print("d = \n", d)

print()
df = pd.DataFrame(d)
print("df=\n", df)
d = 
 [(0, 0.) (0, 0.) (0, 0.)]

df=
    A    B
0  0  0.0
1  0  0.0
2  0  0.0

对于DataFrame数据的使用方式,我们以前说过,可以把DataFrame看做是具有行列号和首部标题行的Excel表格,而去除掉列号和首部标题行后,DataFrame就可以看做是一个二维数组。

对于DataFrame的数据选择,可以采用字典形式的访问,此时访问的是一列值,也可以采用切片等,下面详细进行介绍:

dl = [{"个": i, "十":i*10, "百":i*100} for i in range(1,5)]


df = pd.DataFrame(dl)
print("df = \n", df)

df = 
           
0  1  10  100
1  2  20  200
2  3  30  300
3  4  40  400
# 使用字典的方式访问

print("df['百'] =\n",  df['百'] )
df['百'] =
 0    100
1    200
2    300
3    400
Name: , dtype: int64

如果选取的键的名字跟上例中的df的属性名称或者函数不冲突,可以直接采用圆点符号进行访问:

# 上面访问方式等价于下面访问方式
# 但下面访问方式并非通用,可能会引起冲突
print("df.百=\n", df.百)
df.=
 0    100
1    200
2    300
3    400
Name: , dtype: int64

DataFrame可以看做是一个增强版的二维数组,此时他的全部值可以用DataFrame.values来表示:

# values属性的使用
print("df.values = \n", df.values)
df.values = 
 [[  1  10 100]
 [  2  20 200]
 [  3  30 300]
 [  4  40 400]]

对于DataFrame的访问,推荐时候用loc,iloc或者ix三个所引器进行访问,避免引起混淆:

# 使用loc进行显示访问
print('df.loc[:2, :"十"]=\n', df.loc[:2, :"十"])
df.loc[:2, :"十"]=
       
0  1  10
1  2  20
2  3  30
# 时候iloc进行隐式访问
print('df.iloc[:2, :2] = \n', df.iloc[:2, :2])
df.iloc[:2, :2] = 
       
0  1  10
1  2  20
# 或者使用ix进行混合访问
# indexing的初衷是避免访问混淆,但ix显然并没有达到这一点,所以,ix索引器不推荐使用
# 使用ix访问,可能会引起警告错误

print(df.ix[:2, :"十"])
      
0  1  10
1  2  20
2  3  30


/Users/augs/anaconda3/lib/python3.7/site-packages/ipykernel_launcher.py:5: DeprecationWarning: 
.ix is deprecated. Please use
.loc for label based indexing or
.iloc for positional indexing

See the documentation here:
http://pandas.pydata.org/pandas-docs/stable/indexing.html#ix-indexer-is-deprecated
  """

2.3. pandas.Index对象

Pandas的Index对象是一个独立的对象,用来表示数据的索引,可以把它看做不可变的数组(tuple)或者有序的集合。

当作为不可变数组的时候,除了数组的一些读操作外,还具有一些NumPy数组的属性。

Index作为有序集合操作主要是为了进行一些基于集合的操作,比如集合的交差并补操作。

# Idnex作为不可变数组

idx = pd.Index([2,4,6,8,10])
print("idx = ", idx)
print("idx[1:4] = ", idx[1:4])
print("idx.size=", idx.size)
print("idx.shape=", idx.shape)
print("idx.ndim", idx.ndim)
print("idx.dtype=", idx.dtype)
idx =  Int64Index([2, 4, 6, 8, 10], dtype='int64')
idx[1:4] =  Int64Index([4, 6, 8], dtype='int64')
idx.size= 5
idx.shape= (5,)
idx.ndim 1
idx.dtype= int64
# Index作为有序集合

idx_1 = pd.Index([1,3,5,6,7,])
idx_2 = pd.Index([2,4,6,7,8,9])

print("交集: idx_1 & idx_2 = ", idx_1 & idx_2)
print("并集: idx_1 | idx_2 = ", idx_1 | idx_2)
print("异或: idx_1 ^ idx_2 = ", idx_1 ^ idx_2)
交集: idx_1 & idx_2 =  Int64Index([6, 7], dtype='int64')
并集: idx_1 | idx_2 =  Int64Index([1, 2, 3, 4, 5, 6, 7, 8, 9], dtype='int64')
异或: idx_1 ^ idx_2 =  Int64Index([1, 2, 3, 4, 5, 8, 9], dtype='int64')