pandas

Numpy 和 Pandas 有什么不同

如果用 python 的列表和字典来作比较, 那么可以说 Numpy 是列表形式的,没有数值标签,而 Pandas 就是字典形式。Pandas是基于Numpy构建的,让Numpy为中心的应用变得更加简单。

 

要使用pandas,首先需要了解他主要两个数据结构:Series和DataFrame。

 1 import pandas as pd
 2 import numpy as np
 3 s = pd.Series([1,3,6,np.nan,44,1])
 4 
 5 print(s)
 6 """
 7 0     1.0
 8 1     3.0
 9 2     6.0
10 3     NaN
11 4    44.0
12 5     1.0
13 dtype: float64
14 """

Series的字符串表现形式为:索引在左边,值在右边。由于我们没有为数据指定索引。于是会自动创建一个0到N-1(N为长度)的整数型索引。

 

DataFrame

 1 dates = pd.date_range('20160101',periods=6)
 2 df = pd.DataFrame(np.random.randn(6,4),index=dates,columns=['a','b','c','d'])
 3 # np.random.randn是从标准正态分布中返回一个或多个样本值,numpy.random.rand的随机样本位于[0, 1)中。
 4 print(df)
 5 """
 6                    a         b         c         d
 7 2016-01-01 -0.253065 -2.071051 -0.640515  0.613663
 8 2016-01-02 -1.147178  1.532470  0.989255 -0.499761
 9 2016-01-03  1.221656 -2.390171  1.862914  0.778070
10 2016-01-04  1.473877 -0.046419  0.610046  0.204672
11 2016-01-05 -1.584752 -0.700592  1.487264 -1.778293
12 2016-01-06  0.633675 -1.414157 -0.277066 -0.442545
13 """

DataFrame是一个表格型的数据结构,它包含有一组有序的列,每列可以是不同的值类型(数值,字符串,布尔值等)。DataFrame既有行索引也有列索引, 它可以被看做由Series组成的大字典。

 

我们可以根据每一个不同的索引来挑选数据, 比如挑选 b 的元素:

 

DataFrame 的一些简单运用

 1 print(df['b'])
 2 
 3 """
 4 2016-01-01   -2.071051
 5 2016-01-02    1.532470
 6 2016-01-03   -2.390171
 7 2016-01-04   -0.046419
 8 2016-01-05   -0.700592
 9 2016-01-06   -1.414157
10 Freq: D, Name: b, dtype: float64
11 """

df1

1 df1 = pd.DataFrame(np.arange(12).reshape((3,4)))
2 print(df1)
3 
4 """
5    0  1   2   3
6 0  0  1   2   3
7 1  4  5   6   7
8 2  8  9  10  11
9 """

这样,他就会采取默认的从0开始 index. 还有一种生成 df 的方法, 如下 df2:

 1 df2 = pd.DataFrame({'A' : 1.,
 2                     'B' : pd.Timestamp('20130102'),
 3                     'C' : pd.Series(1,index=list(range(4)),dtype='float32'),
 4                     'D' : np.array([3] * 4,dtype='int32'),
 5                     'E' : pd.Categorical(["test","train","test","train"]),
 6                     'F' : 'foo'})
 7 
 8 print(df2)
 9 
10 """
11      A          B    C  D      E    F
12 0  1.0 2013-01-02  1.0  3   test  foo
13 1  1.0 2013-01-02  1.0  3  train  foo
14 2  1.0 2013-01-02  1.0  3   test  foo
15 3  1.0 2013-01-02  1.0  3  train  foo
16 """

这种方法能对每一列的数据进行特殊对待. 如果想要查看数据中的类型, 我们可以用 dtype 这个属性:

 1 print(df2.dtypes)
 2 
 3 """
 4 df2.dtypes
 5 A           float64
 6 B    datetime64[ns]
 7 C           float32
 8 D             int32
 9 E          category
10 F            object
11 dtype: object
12 """

如果想看对列的序号:

 

print(df2.index)

 

# Int64Index([0, 1, 2, 3], dtype='int64')

1

2

3

同样, 每种数据的名称也能看到:

 

print(df2.columns)

 

# Index(['A', 'B', 'C', 'D', 'E', 'F'], dtype='object')

1

2

3

如果只想看所有df2的值:

 

print(df2.values)

 

"""

array([[1.0, Timestamp('2013-01-02 00:00:00'), 1.0, 3, 'test', 'foo'],

       [1.0, Timestamp('2013-01-02 00:00:00'), 1.0, 3, 'train', 'foo'],

       [1.0, Timestamp('2013-01-02 00:00:00'), 1.0, 3, 'test', 'foo'],

       [1.0, Timestamp('2013-01-02 00:00:00'), 1.0, 3, 'train', 'foo']], dtype=object)

"""

 

想知道数据的总结, 可以用 describe():

 

df2.describe()

 

"""

         A C D

count 4.0 4.0 4.0

mean 1.0 1.0 3.0

std 0.0 0.0 0.0

min 1.0 1.0 3.0

25% 1.0 1.0 3.0

50% 1.0 1.0 3.0

75% 1.0 1.0 3.0

max 1.0 1.0 3.0

"""

如果想翻转数据, transpose:

 

print(df2.T)

 

"""                   

0 1 2

A 1 1 1   

B 2013-01-02 00:00:00 2013-01-02 00:00:00 2013-01-02 00:00:00   

C 1 1 1   

D 3 3 3   

E test train test   

F foo foo foo   

 

                     3  

A 1  

B 2013-01-02 00:00:00  

C 1  

D 3  

E train  

F foo  

 

"""

如果想对数据的 index 进行排序并输出:

 

print(df2.sort_index(axis=1, ascending=False))

 

"""

     F E D C B A

0 foo test 3 1.0 2013-01-02 1.0

1 foo train 3 1.0 2013-01-02 1.0

2 foo test 3 1.0 2013-01-02 1.0

3 foo train 3 1.0 2013-01-02 1.0

""

 

ascending=False是倒序,如果要正序则输入True

 

如果是对数据 值 排序输出:

 

print(df2.sort_values(by='B'))

 

"""

     A B C D E F

0 1.0 2013-01-02 1.0 3 test foo

1 1.0 2013-01-02 1.0 3 train foo

2 1.0 2013-01-02 1.0 3 test foo

3 1.0 2013-01-02 1.0 3 train foo

"""

Pandas选择数据

我们建立了一个 6X4 的矩阵数据。

 

dates = pd.date_range('20130101', periods=6)

df = pd.DataFrame(np.arange(24).reshape((6,4)),index=dates, columns=['A','B','C','D'])

 

"""

             A B C D

2013-01-01 0 1 2 3

2013-01-02 4 5 6 7

2013-01-03 8 9 10 11

2013-01-04 12 13 14 15

2013-01-05 16 17 18 19

2013-01-06 20 21 22 23

"""

 

简单的筛选

如果我们想选取DataFrame中的数据,下面描述了两种途径, 他们都能达到同一个目的:

 

print(df['A'])

print(df.A)

 

"""

2013-01-01 0

2013-01-02 4

2013-01-03 8

2013-01-04 12

2013-01-05 16

2013-01-06 20

Freq: D, Name: A, dtype: int64

"""

让选择跨越多行或多列:

 

print(df[0:3])

 

"""

            A B C D

2013-01-01 0 1 2 3

2013-01-02 4 5 6 7

2013-01-03 8 9 10 11

"""

 

print(df['20130102':'20130104'])

 

"""

A B C D

2013-01-02 4 5 6 7

2013-01-03 8 9 10 11

2013-01-04 12 13 14 15

"""

如果df[3:3]将会是一个空对象。后者选择20130102到20130104标签之间的数据,并且包括这两个标签。

 

根据标签 loc

同样我们可以使用标签来选择数据 loc, 本例子主要通过标签名字选择某一行数据, 或者通过选择某行或者所有行(:代表所有行)然后选其中某一列或几列数据。:

 

print(df.loc['20130102'])

"""

A 4

B 5

C 6

D 7

Name: 2013-01-02 00:00:00, dtype: int64

"""

 

print(df.loc[:,['A','B']]) 

"""

             A B

2013-01-01 0 1

2013-01-02 4 5

2013-01-03 8 9

2013-01-04 12 13

2013-01-05 16 17

2013-01-06 20 21

"""

 

print(df.loc['20130102',['A','B']])

"""

A 4

B 5

Name: 2013-01-02 00:00:00, dtype: int64

"""

根据序列 iloc

另外我们可以采用位置进行选择 iloc, 在这里我们可以通过位置选择在不同情况下所需要的数据例如选某一个,连续选或者跨行选等操作。

 

print(df.iloc[3,1])

# 13

 

print(df.iloc[3:5,1:3])

"""

             B C

2013-01-04 13 14

2013-01-05 17 18

"""

 

print(df.iloc[[1,3,5],1:3])

"""

             B C

2013-01-02 5 6

2013-01-04 13 14

2013-01-06 21 22

 

"""

在这里我们可以通过位置选择在不同情况下所需要的数据, 例如选某一个,连续选或者跨行选等操作。

 

根据混合的这两种 ix

当然我们可以采用混合选择 ix, 其中选择’A’和’C’的两列,并选择前三行的数据。

 

print(df.ix[:3,['A','C']])

"""

            A C

2013-01-01 0 2

2013-01-02 4 6

2013-01-03 8 10

"""

通过判断的筛选

最后我们可以采用判断指令 (Boolean indexing) 进行选择. 我们可以约束某项条件然后选择出当前所有数据.

 

print(df[df.A>8])

"""

             A B C D

2013-01-04 12 13 14 15

2013-01-05 16 17 18 19

2013-01-06 20 21 22 23

"""

Pandas设置值

创建数据

我们可以根据自己的需求, 用 pandas 进行更改数据里面的值, 或者加上一些空的,或者有数值的列.

 

首先建立了一个 6X4 的矩阵数据。

 

dates = pd.date_range('20130101', periods=6)

df = pd.DataFrame(np.arange(24).reshape((6,4)),index=dates, columns=['A','B','C','D'])

 

"""

             A B C D

2013-01-01 0 1 2 3

2013-01-02 4 5 6 7

2013-01-03 8 9 10 11

2013-01-04 12 13 14 15

2013-01-05 16 17 18 19

2013-01-06 20 21 22 23

"""

根据位置设置 loc 和 iloc

我们可以利用索引或者标签确定需要修改值的位置。

 

df.iloc[2,2] = 1111

df.loc['20130101','B'] = 2222

 

"""

             A B C D

2013-01-01 0 2222 2 3

2013-01-02 4 5 6 7

2013-01-03 8 9 1111 11

2013-01-04 12 13 14 15

2013-01-05 16 17 18 19

2013-01-06 20 21 22 23

"""

根据条件设置

如果现在的判断条件是这样, 我们想要更改B中的数, 而更改的位置是取决于 A 的. 对于A大于4的位置. 更改B在相应位置上的数为0.

 

df.B[df.A>4] = 0

"""

                A B C D

2013-01-01 0 2222 2 3

2013-01-02 4 5 6 7

2013-01-03 8 0 1111 11

2013-01-04 12 0 14 15

2013-01-05 16 0 18 19

2013-01-06 20 0 22 23 

"""

按行或列设置

如果对整列做批处理, 加上一列 ‘F’, 并将 F 列全改为 NaN, 如下:

 

df['F'] = np.nan

"""

             A B C D F

2013-01-01 0 2222 2 3 NaN

2013-01-02 4 5 6 7 NaN

2013-01-03 8 0 1111 11 NaN

2013-01-04 12 0 14 15 NaN

2013-01-05 16 0 18 19 NaN

2013-01-06 20 0 22 23 NaN

""

添加数据

用上面的方法也可以加上 Series 序列(但是长度必须对齐)。

 

df['E'] = pd.Series([1,2,3,4,5,6], index=pd.date_range('20130101',periods=6)) 

"""

             A B C D F E

2013-01-01 0 2222 2 3 NaN 1

2013-01-02 4 5 6 7 NaN 2

2013-01-03 8 0 1111 11 NaN 3

2013-01-04 12 0 14 15 NaN 4

2013-01-05 16 0 18 19 NaN 5

2013-01-06 20 0 22 23 NaN 6

"""

这样我们大概学会了如何对DataFrame中在自己想要的地方赋值或者增加数据。

 

Pandas处理丢失数据

创建含 NaN 的矩阵

有时候我们导入或处理数据, 会产生一些空的或者是 NaN 数据,如何删除或者是填补这些 NaN 数据就是我们今天所要提到的内容.

 

建立了一个6X4的矩阵数据并且把两个位置置为空.

 

dates = pd.date_range('20130101', periods=6)

df = pd.DataFrame(np.arange(24).reshape((6,4)),index=dates, columns=['A','B','C','D'])

df.iloc[0,1] = np.nan

df.iloc[1,2] = np.nan

"""

             A B C D

2013-01-01 0 NaN 2.0 3

2013-01-02 4 5.0 NaN 7

2013-01-03 8 9.0 10.0 11

2013-01-04 12 13.0 14.0 15

2013-01-05 16 17.0 18.0 19

2013-01-06 20 21.0 22.0 23

"""

pd.dropna()

如果想直接去掉有 NaN 的行或列, 可以使用 dropna

 

df.dropna(

    axis=0, # 0: 对行进行操作; 1: 对列进行操作

    how='any' # 'any': 只要存在 NaN 就 drop 掉; 'all': 必须全部是 NaN 才 drop 

    ) 

"""

             A B C D

2013-01-03 8 9.0 10.0 11

2013-01-04 12 13.0 14.0 15

2013-01-05 16 17.0 18.0 19

2013-01-06 20 21.0 22.0 23

"""

pd.fillna()

如果是将 NaN 的值用其他值代替, 比如代替成 0:

 

df.fillna(value=0)

"""

             A B C D

2013-01-01 0 0.0 2.0 3

2013-01-02 4 5.0 0.0 7

2013-01-03 8 9.0 10.0 11

2013-01-04 12 13.0 14.0 15

2013-01-05 16 17.0 18.0 19

2013-01-06 20 21.0 22.0 23

"""

pd.isnull()

判断是否有缺失数据 NaN, 为 True 表示缺失数据:

 

df.isnull() 

"""

                A B C D

2013-01-01 False True False False

2013-01-02 False False True False

2013-01-03 False False False False

2013-01-04 False False False False

2013-01-05 False False False False

2013-01-06 False False False False

"""

检测在数据中是否存在 NaN, 如果存在就返回 True:

 

np.any(df.isnull()) == True  

# True

1

2

Pandas导入导出

要点

pandas可以读取与存取的资料格式有很多种,像csv、excel、json、html与pickle等…, 详细请看官方说明文件

 

读取csv

import pandas as pd #加载模块

 

#读取csv

data = pd.read_csv('student.csv')

 

#打印出data

print(data)

将资料存取成pickle

data.to_pickle('student.pickle')

1

Pandas合并concat

要点

pandas处理多组数据的时候往往会要用到数据的合并处理,使用 concat是一种基本的合并方式.而且concat中有很多参数可以调整,合并成你想要的数据形式.

 

axis (合并方向)

axis=0是预设值,因此未设定任何参数时,函数默认axis=0。

 

import pandas as pd

import numpy as np

 

#定义资料集

df1 = pd.DataFrame(np.ones((3,4))*0, columns=['a','b','c','d'])

df2 = pd.DataFrame(np.ones((3,4))*1, columns=['a','b','c','d'])

df3 = pd.DataFrame(np.ones((3,4))*2, columns=['a','b','c','d'])

 

#concat纵向合并

res = pd.concat([df1, df2, df3], axis=0)

 

#打印结果

print(res)

# a b c d

# 0 0.0 0.0 0.0 0.0

# 1 0.0 0.0 0.0 0.0

# 2 0.0 0.0 0.0 0.0

# 0 1.0 1.0 1.0 1.0

# 1 1.0 1.0 1.0 1.0

# 2 1.0 1.0 1.0 1.0

# 0 2.0 2.0 2.0 2.0

# 1 2.0 2.0 2.0 2.0

# 2 2.0 2.0 2.0 2.0

仔细观察会发现结果的index是0, 1, 2, 0, 1, 2, 0, 1, 2

 

ignore_index (重置 index)

#承上一个例子,并将index_ignore设定为True

res = pd.concat([df1, df2, df3], axis=0, ignore_index=True)

 

#打印结果

print(res)

# a b c d

# 0 0.0 0.0 0.0 0.0

# 1 0.0 0.0 0.0 0.0

# 2 0.0 0.0 0.0 0.0

# 3 1.0 1.0 1.0 1.0

# 4 1.0 1.0 1.0 1.0

# 5 1.0 1.0 1.0 1.0

# 6 2.0 2.0 2.0 2.0

# 7 2.0 2.0 2.0 2.0

# 8 2.0 2.0 2.0 2.0

结果的index变0, 1, 2, 3, 4, 5, 6, 7, 8。

 

join (合并方式)

join=’outer’为预设值,因此未设定任何参数时,函数默认join=’outer’。此方式是依照column来做纵向合并,有相同的column上下合并在一起,其他独自的column个自成列,原本没有值的位置皆以NaN填充。

 

import pandas as pd

import numpy as np

 

#定义资料集

df1 = pd.DataFrame(np.ones((3,4))*0, columns=['a','b','c','d'], index=[1,2,3])

df2 = pd.DataFrame(np.ones((3,4))*1, columns=['b','c','d','e'], index=[2,3,4])

 

#纵向"外"合并df1与df2

res = pd.concat([df1, df2], axis=0, join='outer')

 

print(res)

# a b c d e

# 1 0.0 0.0 0.0 0.0 NaN

# 2 0.0 0.0 0.0 0.0 NaN

# 3 0.0 0.0 0.0 0.0 NaN

# 2 NaN 1.0 1.0 1.0 1.0

# 3 NaN 1.0 1.0 1.0 1.0

# 4 NaN 1.0 1.0 1.0 1.0

原理同上个例子的说明,但只有相同的column合并在一起,其他的会被抛弃。

 

#承上一个例子

 

#纵向"内"合并df1与df2

res = pd.concat([df1, df2], axis=0, join='inner')

 

#打印结果

print(res)

# b c d

# 1 0.0 0.0 0.0

# 2 0.0 0.0 0.0

# 3 0.0 0.0 0.0

# 2 1.0 1.0 1.0

# 3 1.0 1.0 1.0

# 4 1.0 1.0 1.0

 

#重置index并打印结果

res = pd.concat([df1, df2], axis=0, join='inner', ignore_index=True)

print(res)

# b c d

# 0 0.0 0.0 0.0

# 1 0.0 0.0 0.0

# 2 0.0 0.0 0.0

# 3 1.0 1.0 1.0

# 4 1.0 1.0 1.0

# 5 1.0 1.0 1.0

join_axes (依照 axes 合并)

import pandas as pd

import numpy as np

 

#定义资料集

df1 = pd.DataFrame(np.ones((3,4))*0, columns=['a','b','c','d'], index=[1,2,3])

df2 = pd.DataFrame(np.ones((3,4))*1, columns=['b','c','d','e'], index=[2,3,4])

 

#依照`df1.index`进行横向合并

res = pd.concat([df1, df2], axis=1, join_axes=[df1.index])

 

#打印结果

print(res)

# a b c d b c d e

# 1 0.0 0.0 0.0 0.0 NaN NaN NaN NaN

# 2 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0

# 3 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0

 

#移除join_axes,并打印结果

res = pd.concat([df1, df2], axis=1)

print(res)

# a b c d b c d e

# 1 0.0 0.0 0.0 0.0 NaN NaN NaN NaN

# 2 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0

# 3 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0

# 4 NaN NaN NaN NaN 1.0 1.0 1.0 1.0

append (添加数据)

append只有纵向合并,没有横向合并。

 

import pandas as pd

import numpy as np

 

#定义资料集

df1 = pd.DataFrame(np.ones((3,4))*0, columns=['a','b','c','d'])

df2 = pd.DataFrame(np.ones((3,4))*1, columns=['a','b','c','d'])

df3 = pd.DataFrame(np.ones((3,4))*1, columns=['a','b','c','d'])

s1 = pd.Series([1,2,3,4], index=['a','b','c','d'])

 

#将df2合并到df1的下面,以及重置index,并打印出结果

res = df1.append(df2, ignore_index=True)

print(res)

# a b c d

# 0 0.0 0.0 0.0 0.0

# 1 0.0 0.0 0.0 0.0

# 2 0.0 0.0 0.0 0.0

# 3 1.0 1.0 1.0 1.0

# 4 1.0 1.0 1.0 1.0

# 5 1.0 1.0 1.0 1.0

 

#合并多个df,将df2与df3合并至df1的下面,以及重置index,并打印出结果

res = df1.append([df2, df3], ignore_index=True)

print(res)

# a b c d

# 0 0.0 0.0 0.0 0.0

# 1 0.0 0.0 0.0 0.0

# 2 0.0 0.0 0.0 0.0

# 3 1.0 1.0 1.0 1.0

# 4 1.0 1.0 1.0 1.0

# 5 1.0 1.0 1.0 1.0

# 6 1.0 1.0 1.0 1.0

# 7 1.0 1.0 1.0 1.0

# 8 1.0 1.0 1.0 1.0

 

#合并series,将s1合并至df1,以及重置index,并打印出结果

res = df1.append(s1, ignore_index=True)

print(res)

# a b c d

# 0 0.0 0.0 0.0 0.0

# 1 0.0 0.0 0.0 0.0

# 2 0.0 0.0 0.0 0.0

# 3 1.0 2.0 3.0 4.0

 

你可能感兴趣的