44.Python编程:Pandas详解

什么是pandas

pandaspython的一个数据分析包,是基于NumPy的一种工具,该工具是为了解决数据分析任务而创建的。pandas纳入了大量库和一些标准的数据模型,提供了高效地操作大型数据集所需的工具。pandas提供了大量能使我们快速便捷地处理数据的函数和方法。

pandas最初被作为金融数据分析工具而开发出来,因此,pandas为时间序列分析提供了很好的支持。 Pandas的名称来自于面板数据(panel data)python数据分析(data analysis)

panel data是经济学中关于多维数据集的一个术语,在Pandas中也提供了panel的数据类型。

简言之,pandas是基于NumPy的,两者是数据分析强大的工具。

pandas安装

pandas安装指令:

pip install pandas

pandas中数据结构Series和DataFrame

pandas中主要有两种数据结构,分别是:Series和DataFrame

Series

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

创建Series对象,用到pandas中的Series()

  • 通过一维数组创建Series对象

创建数据是一维数组,也可以是字典。前面一文NumPy详解中,已详细学习了NumPy一维数组的各种创建,此处不再赘述。我们只需把创建好的一维数组数据传递过来即可。示例如下:

import pandas as pd
import numpy as np

# Series

# 通过随机数创建numpy数组
arr = np.random.randn(6)
s1 = pd.Series(arr)
print(s1)
print("-" * 20)

# 通过arange()创建numpy数组
arr2 = np.arange(6)
s2 = pd.Series(arr2)
print(s2)
print("-" * 20)

# 通过ones创建numpy的全1数组
arr3 = np.ones(6)
s3 = pd.Series(arr3)
print(s3)
print("-" * 20)

# 通过zeros创建numpy的全零数组
arr4 = np.zeros(6)
s4 = pd.Series(arr4)
print(s4)

运行结果:

0   -1.205245
1   -0.671404
2   -0.056164
3   -0.090229
4    1.004950
5   -1.139511
dtype: float64
--------------------
0    0
1    1
2    2
3    3
4    4
5    5
dtype: int32
--------------------
0    1.0
1    1.0
2    1.0
3    1.0
4    1.0
5    1.0
dtype: float64
--------------------
0    0.0
1    0.0
2    0.0
3    0.0
4    0.0
5    0.0
dtype: float64

说明:
上面例子中,我们在创建Series对象,只提供了数据源,并没有提供索引。此时索引默认是从0开始的数字,依次排序。当然,我们也可以在创建的时候,指定索引:

import pandas as pd
import numpy as np

# Series

# 创建的时候,指定索引
arr = np.random.randn(6)
s5 = pd.Series(arr, index=["一月", "二月", "三月", "四月", "五月", "六月"])
print(s5)

运行结果:

一月    0.088578
二月    0.347118
三月   -1.080161
四月   -0.937341
五月    1.216052
六月    0.646635
dtype: float64
  • 通过字典创建Series对象

上面例子中,我们在创建Series对象,数据源是一维数组,当然我们也可以传入字典来创建Series对象。字典的key就是要生成Series的索引了。

import pandas as pd

# Series

dict_data = {"一月": 11, "二月": 13, "三月": 10, "四月": 14, "五月": 8, "六月": 10}

# 通过字典创建Series对象
s3 = pd.Series(dict_data)
print(s3)

运行结果:

一月    11
二月    13
三月    10
四月    14
五月     8
六月    10
dtype: int64
  • 取值

我们从Series数据结构中取值,可以利用自定义的索引标签,也可以利用默认的位置索引。上面例子中可以这样取值:

# 上接

# 通过标签取值
print(s3["一月"])

# 通过默认的索引序列取值
print(s3[0])

运行结果:

11
11

Series一维数据结构很简单,我们重点去学习二维数据结构DataFrame

注意:Series中的索引值是可以重复的。

DataFrame

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

DataFrame对象的创建,要用到pandas 中的DataFrame()。需要传入的参数,数据源可以是二维数组,也可以是字典。除此之外,创建的同时也可以指定行索引,列索引。如果不指定索引,将使用默认的索引,从0开始的依次递增的序列号。

import pandas as pd
import numpy as np

# DataFrame

# 利用numpy创建二维数据
arr = np.random.randn(20).reshape((4, 5))

# 利用pandas创建DataFrame对象
df = pd.DataFrame(arr)

print(df)

运行结果:

          0         1         2         3         4
0 -1.719292  0.437608  0.512311 -0.658363 -0.114165
1 -0.730688  1.887302  0.495906  0.109294  0.484358
2  2.716056 -2.124497 -0.406951  1.396759  1.621959
3  1.923468 -0.129051  0.218899  2.427141  0.781985

我们可以在创建的同时,可以指定行索引、列索引。示例如下:

import pandas as pd
import numpy as np

# DataFrame

# 利用numpy创建二维数据
arr = np.random.randn(20).reshape((4, 5))

# 行索引
index = ["Q1", "Q2", "Q3", "Q4"]

# 列索引
columns = ["A", "B", "C", "D", "E"]

# 利用pandas创建DataFrame对象
df = pd.DataFrame(arr, index=index, columns=columns)

print(df)

运行结果:

           A         B         C         D         E
Q1  0.064423  1.633352 -1.705736  1.305984  0.001379
Q2  0.445133  0.452308  1.659449 -0.800272  0.986402
Q3 -0.024076  1.090810 -0.627166 -0.312072  0.242472
Q4 -2.754748 -0.757759  0.689985 -0.001170 -0.136409
常见属性

我们可以获取行索引df.index、列索引df.columns、数据值df.values、数据描述df.describe(),示例如下:

import pandas as pd
import numpy as np

# DataFrame

# 利用numpy创建二维数据
arr = np.random.randn(20).reshape((4, 5))

# 行索引
index = ["Q1", "Q2", "Q3", "Q4"]

# 列索引
columns = ["A", "B", "C", "D", "E"]

# 利用pandas创建DataFrame对象
df = pd.DataFrame(arr, index=index, columns=columns)

print(df)
print("-" * 50)

# 行索引
print(df.index)

# 列索引
print(df.columns)
print("-" * 50)

# 数据值
print(df.values)

print("-" * 50)

# 数据描述信息
print(df.describe())

运行结果:

           A         B         C         D         E
Q1  0.752826 -1.355122  0.035948  0.839446  0.635179
Q2 -0.496016 -0.322719  0.885232  0.247262 -0.906780
Q3  0.845926  1.073606  0.233991 -0.236160  0.147905
Q4  0.030459  1.391417 -0.346198  1.991587 -0.303235
--------------------------------------------------
Index(['Q1', 'Q2', 'Q3', 'Q4'], dtype='object')
Index(['A', 'B', 'C', 'D', 'E'], dtype='object')
--------------------------------------------------
[[ 0.75282594 -1.35512209  0.03594756  0.83944646  0.63517926]
 [-0.49601568 -0.32271876  0.8852321   0.24726162 -0.90678047]
 [ 0.84592563  1.07360619  0.23399063 -0.23615957  0.14790464]
 [ 0.03045917  1.39141744 -0.34619834  1.99158653 -0.30323524]]
--------------------------------------------------
              A         B         C         D         E
count  4.000000  4.000000  4.000000  4.000000  4.000000
mean   0.283299  0.196796  0.202243  0.710534 -0.106733
std    0.634629  1.274658  0.515081  0.960653  0.656750
min   -0.496016 -1.355122 -0.346198 -0.236160 -0.906780
25%   -0.101160 -0.580820 -0.059589  0.126406 -0.454122
50%    0.391643  0.375444  0.134969  0.543354 -0.077665
75%    0.776101  1.153059  0.396801  1.127481  0.269723
max    0.845926  1.391417  0.885232  1.991587  0.635179

说明:通过df.describe()获取的数据描述信息,包含了每一列数据的总个数count、每一列平均值mean、每一列标准差std、每一列最小值min、每一列最大值max等信息。

排序sort

排序可以根据索引排序df.sort_index(axis=0, ascending=False),其中,axis=0或1等,0表示竖直方向上对行排序,1表示水平方向上对列排序,ascending=True或False,表示是按升序还按照降序排序。

import pandas as pd
import numpy as np

# 利用numpy创建二维数据
arr = np.random.randn(20).reshape((4, 5))

# 行索引
index = ["Q1", "Q2", "Q3", "Q4"]

# 列索引
columns = ["A", "B", "C", "D", "E"]

# 利用pandas创建DataFrame对象
df = pd.DataFrame(arr, index=index, columns=columns)

print(df)

# 按行索引降序排序
print(df.sort_index(axis=0, ascending=False))

运行结果:

           A         B         C         D         E
Q1  1.204422 -0.670984 -0.068458 -1.694837 -0.091393
Q2 -0.359985 -0.043025  2.100953  0.093833  0.523428
Q3  0.234466  1.977082  1.352345  1.378801  0.399397
Q4 -1.641561  0.036706  1.189736 -0.076161 -0.500466
           A         B         C         D         E
Q4 -1.641561  0.036706  1.189736 -0.076161 -0.500466
Q3  0.234466  1.977082  1.352345  1.378801  0.399397
Q2 -0.359985 -0.043025  2.100953  0.093833  0.523428
Q1  1.204422 -0.670984 -0.068458 -1.694837 -0.091393

说明:按照行或列索引排序,索引是排好序的,但值不一定是排好序的。

也可以根据值排序df.sort_values(axis=0, by="A", ascending=False),根据值排序时,要传入根据哪一行或哪一列的数据排序。

特别注意的是,如果axis=0,表示既然竖直方向上对行排序,则此时by="标签名"标签名只能传入列标签名,表示依据此列元素的值排序。同理,如果axis=1,表示既然水平方向上对行排序,则此时by="标签名"标签名只能传入行标签名,表示依据此行元素的值进行排序。

import pandas as pd
import numpy as np

# 利用numpy创建二维数据
arr = np.random.randn(20).reshape((4, 5))

# 行索引
index = ["Q1", "Q2", "Q3", "Q4"]

# 列索引
columns = ["A", "B", "C", "D", "E"]

# 利用pandas创建DataFrame对象
df = pd.DataFrame(arr, index=index, columns=columns)

print(df)

# 对数据值,根据A列数据的值,降序排序
print(df.sort_values(axis=0, by="A", ascending=False))

print("-" * 50)

# 对数据值,根据Q1行数据的值,升序排序
print(df.sort_values(axis=1, by="Q1", ascending=True))

运行结果:

           A         B         C         D         E
Q1 -0.732549 -1.738364  0.651045 -0.639112 -2.327446
Q2 -2.366076 -0.090833 -0.070340 -0.373408 -0.195486
Q3 -0.270237 -0.087023 -0.185530  0.600220  1.122631
Q4  0.486386  1.656176  0.667432  0.718930 -1.326645

           A         B         C         D         E
Q4  0.486386  1.656176  0.667432  0.718930 -1.326645
Q3 -0.270237 -0.087023 -0.185530  0.600220  1.122631
Q1 -0.732549 -1.738364  0.651045 -0.639112 -2.327446
Q2 -2.366076 -0.090833 -0.070340 -0.373408 -0.195486
--------------------------------------------------
           E         B         A         D         C
Q1 -2.327446 -1.738364 -0.732549 -0.639112  0.651045
Q2 -0.195486 -0.090833 -2.366076 -0.373408 -0.070340
Q3  1.122631 -0.087023 -0.270237  0.600220 -0.185530
Q4 -1.326645  1.656176  0.486386  0.718930  0.667432

选择数据

DataFrame选择数据可以通过行、列标签名df.loc[标签名],也可以通过索引df.iloc[索引值或切片],也可混合上面两种取值df.ix[标签名, 索引值或切片]

  • 通过行、列标签名选择数据

通过行、列标签名选择数据,用到df.loc[标签名],示例如下:

数据源:

           A         B         C         D         E         F
R0  1.011527 -1.682691 -0.638201 -0.209897  0.349887 -0.238343
R1 -2.226714 -0.903630 -0.538594  2.001834  2.235736 -0.759220
R2 -0.351387 -0.003949  0.686346 -0.103567  0.800941 -1.399295
R3 -0.001803 -1.968112 -0.147488  1.152809  0.598925  0.549745
R4  0.604023  0.417916  0.544499 -0.895700 -0.323974 -2.276000

根据行标签取一整行:

# 根据行标签取一整行
df.loc["R0"]

得到数据:

A    1.011527
B   -1.682691
C   -0.638201
D   -0.209897
E    0.349887
F   -0.238343
Name: R0, dtype: float64

根据列标签取一整列:

# 根据列标签取一整列
print(df.loc[:, "A"])

得到数据:

R0    1.011527
R1   -2.226714
R2   -0.351387
R3   -0.001803
R4    0.604023
Name: A, dtype: float64

根据行标签取R0、R1、R2,3整行:

# 根据行标签取R0、R1、R2,3整行
df.loc["R0":"R2"]

得到数据:

           A         B         C         D         E         F
R0  1.011527 -1.682691 -0.638201 -0.209897  0.349887 -0.238343
R1 -2.226714 -0.903630 -0.538594  2.001834  2.235736 -0.759220
R2 -0.351387 -0.003949  0.686346 -0.103567  0.800941 -1.399295


根据行标签取R0行中在A、B、C 三列中的元素:

# 根据行标签取R0行中在A、B、C 三列中的元素
df.loc["R0", "A":"C"]

得到数据:

A    1.011527
B   -1.682691
C   -0.638201
Name: R0, dtype: float64

  • 通过索引选择数据

通过索引选择数据,用到df.iloc[索引值或切片],示例如下:
用到的数据源:

           A         B         C         D         E         F
R0  1.476388 -0.433099 -1.267180  0.494799  0.221961  2.321015
R1 -0.942005  0.120891 -2.199903 -1.065044  0.371607 -1.600735
R2 -0.881376  0.439391 -2.043897  0.153790  0.084514  1.015457
R3  0.133820  0.405521 -0.894834 -0.477888 -0.272330  0.763863
R4 -0.664487  1.887760  1.341702 -0.161265  1.048645  1.391557

根据行索引取一整行:

# 根据行索引取一整行
df.iloc[0]

得到数据:

A    1.476388
B   -0.433099
C   -1.267180
D    0.494799
E    0.221961
F    2.321015
Name: R0, dtype: float64

根据列索引取一整列:

# 根据列索引取一整列
df.iloc[:, 0]

得到数据:

R0    1.476388
R1   -0.942005
R2   -0.881376
R3    0.133820
R4   -0.664487
Name: A, dtype: float64

根据行索引取R0、R1、R2, 3整行:

# 根据行索引取R0、R1、R2, 3整行
df.iloc[0:3]

得到数据:

           A         B         C         D         E         F
R0  1.476388 -0.433099 -1.267180  0.494799  0.221961  2.321015
R1 -0.942005  0.120891 -2.199903 -1.065044  0.371607 -1.600735
R2 -0.881376  0.439391 -2.043897  0.153790  0.084514  1.015457


根据行标签取R0、R1行中在A、B、C 三列中的元素:

# 根据行标签取R0、R1行中在A、B、C 三列中的元素
df.iloc[0:2, 0:3]

得到数据:

           A         B         C
R0  1.476388 -0.433099 -1.267180
R1 -0.942005  0.120891 -2.199903

  • 混合上面两种方式取值

混合上面两种方式取值df.ix[ ],形如:df.ix["R0":"R2", 1:3]
用到的数据源:

           A         B         C         D         E         F
R0  1.966476  0.768749  1.741041 -0.852826  0.803514 -1.820019
R1 -0.077837 -0.187937 -0.043093  0.033061  0.874705  0.788629
R2 -1.069619  1.824115 -1.213599 -1.193291 -0.841343 -0.511017
R3 -1.285230  0.210782 -0.081224  0.929470  0.134794 -0.184362
R4  0.768942 -1.698733  0.510024  0.036163 -0.250046 -2.846145

混合取值:

# 混合取值
print(df.ix["R0":"R2", 1:3])

得到的结果:

           B         C
R0  0.768749  1.741041
R1 -0.187937 -0.043093
R2  1.824115 -1.213599

空数据处理

我们已经知道,pandas是基于numpy的,numpy对某个位置处的数据不存在时用NaN来进行标记。

  • df.isnull()是否空数据

DataFrame对象可以用isnull()判断某个位置处的元素是否为空。不为空,该位置显示为False,为空则显示为True
用到的数据源:

           A         B         C         D         E         F
R0  0.528350       NaN       NaN -0.303180 -1.612900       NaN
R1 -1.879040  0.735716 -1.109263 -0.718037  0.631095  0.174179
R2 -0.655658       NaN       NaN  0.723953  0.777969       NaN
R3 -0.020232       NaN       NaN -1.902687 -0.368842       NaN
R4  0.858285 -1.073122  0.158649 -0.123761  1.075735  1.131269

判断某个位置处的元素是否为空:

df.isnull()

运行结果:

       A      B      C      D      E      F
R0  False   True   True  False  False   True
R1  False  False  False  False  False  False
R2  False   True   True  False  False   True
R3  False   True   True  False  False   True
R4  False  False  False  False  False  False
  • 丢掉空元素

DataFrame对象可以用df.dropna(axis=0, how="any")对含有空元素的行或列进行丢弃。其中入参说明如下:

axis=0或1axis=0表示对行舍弃;axis=1表示对列舍弃;
how="any"或"all"how="any"表示某行或列只要包含有Nan就舍弃该行或列;how="all"表示只有当该行或列所有元素都是Nan,才舍弃该行或列,具体是舍弃行还是舍弃列,依据axis=的值为0还是1

使用到的数据源:

           A         B         C         D         E         F
R0 -0.971986       NaN       NaN -0.068481 -0.514055       NaN
R1       NaN       NaN       NaN       NaN       NaN       NaN
R2 -0.266219       NaN       NaN  0.963201  0.538803       NaN
R3  1.137753       NaN       NaN -0.519390 -2.327215       NaN
R4  1.550748 -0.532099  0.935743 -0.432936 -0.379045 -1.170906

axis=0, how="any"舍弃含有Nan的行:

# axis=0, how="any":舍弃含有Nan的行
print(df.dropna(axis=0, how="any"))

运行结果:

           A         B         C         D         E         F
R4  1.550748 -0.532099  0.935743 -0.432936 -0.379045 -1.170906

说明:由于df.dropna(axis=0, how="any")舍弃含有Nan的行,且数据源中,含有NaN的行是R0、R1、R2、R3,所以将R0、R1、R2、R3行舍弃,仅剩R4行。


axis=0, how="all"舍弃某行元素都为Nan的行:

# axis=0, how="all" 舍弃某行元素都为Nan的行
print(df.dropna(axis=0, how="all"))

运行结果:

           A         B         C         D         E         F
R0 -0.971986       NaN       NaN -0.068481 -0.514055       NaN
R2 -0.266219       NaN       NaN  0.963201  0.538803       NaN
R3  1.137753       NaN       NaN -0.519390 -2.327215       NaN
R4  1.550748 -0.532099  0.935743 -0.432936 -0.379045 -1.170906

说明:由于df.dropna(axis=0, how="all")舍弃某行元素都为Nan的行,且数据源中,所有元素都为NaN的行是R1,所以将R1行舍弃。


新的数据源:

           A         B         C         D         E   F
R0  0.847803       NaN       NaN -0.407275  0.522512 NaN
R1  1.566876 -1.370242  0.485341  0.351113  0.668934 NaN
R2  0.183118       NaN       NaN  1.597792  0.969363 NaN
R3  1.636157       NaN       NaN -0.854254 -0.720455 NaN
R4  0.003340 -0.786744 -0.045098  1.248421  0.344938 NaN

axis=1, how="any"舍弃含有Nan的列:

# axis=1, how="any":舍弃含有Nan的列
print(df.dropna(axis=1, how="any"))

运行结果:

           A         D         E
R0  0.847803 -0.407275  0.522512
R1  1.566876  0.351113  0.668934
R2  0.183118  1.597792  0.969363
R3  1.636157 -0.854254 -0.720455
R4  0.003340  1.248421  0.344938

说明:由于df.dropna(axis=1, how="any")舍弃含有Nan的列,且数据源中,所有元素都为NaN的列是B、C、F,所以将B、C、F列舍弃,剩余A、D、E列。


axis=1, how="all"舍弃某行元素都为Nan的列:

# axis=1, how="all"舍弃某行元素都为Nan的列
print(df.dropna(axis=1, how="all"))

运行结果:

           A         B         C         D         E
R0  0.847803       NaN       NaN -0.407275  0.522512
R1  1.566876 -1.370242  0.485341  0.351113  0.668934
R2  0.183118       NaN       NaN  1.597792  0.969363
R3  1.636157       NaN       NaN -0.854254 -0.720455
R4  0.003340 -0.786744 -0.045098  1.248421  0.344938

说明:由于df.dropna(axis=1, how="all")舍弃某行元素都为Nan的列,且数据源中,所有元素都为NaN的列是F,所以将F列舍弃。


  • NaN填充数据

DataFrame对象可以用fillna(value=1)对含有空元素的值进行重新赋值。

数据源:

           A         B         C         D         E   F
R0  0.150234       NaN       NaN -1.211939 -3.346958 NaN
R1       NaN       NaN       NaN       NaN       NaN NaN
R2  0.198726       NaN       NaN -0.235129  0.912252 NaN
R3 -0.028627       NaN       NaN  0.028133 -0.419417 NaN
R4  0.559427  1.249356  1.091567 -1.201653  0.797971 NaN
print(df.fillna(value=1))

运行结果:

           A         B         C         D         E    F
R0  0.150234  1.000000  1.000000 -1.211939 -3.346958  1.0
R1  1.000000  1.000000  1.000000  1.000000  1.000000  1.0
R2  0.198726  1.000000  1.000000 -0.235129  0.912252  1.0
R3 -0.028627  1.000000  1.000000  0.028133 -0.419417  1.0
R4  0.559427  1.249356  1.091567 -1.201653  0.797971  1.0

数据的合并

Pandas对数据的合并提供了多种实现方式,最常用的有3种:pd.concat()、pd.append()、pd.merge()。下面将一一介绍:

  • pd.concat()方式

pd.concat([df1, df2, df3,...],axis=0或1,ignore_index=True,join="outer"或者"inner", join_axes=[data1.index])

参数说明:
[df1, df2, df3,...]表示要合并的多个DataFrame对象组成的列表;
axis=0或1分别表示在垂直方向合并还是在水平方向合并。
ignore_index=True表示数据合并后重新排序索引,默认不重新排序索引。
join="outer"或者"inner"outer表示向外括展,原来没有值得元素填充为NaN标记;inner表示向内收缩、取交集。只取公共行列的数据,其余的丢弃。
join_axes=[df1.index]如果有join_axes的参数传入,可以指定根据那个轴来对齐数据。例如根据df1表对齐数据,就会保留指定的df1表的轴,然后将别的表与之拼接。

axis=0垂直方向合并:

import pandas as pd
import numpy as np


# 数据的合并

index1 = pd.date_range("2018-10-01", periods=4)
df1 = pd.DataFrame(np.arange(20).reshape((4, 5)), index=index1, columns=list("ABCDE"))
print(df1)

print("-" * 40)

index2 = pd.date_range("2018-10-03", periods=3)
df2 = pd.DataFrame(np.arange(12).reshape((3, 4)), index=index2, columns=list("DEFG"))
print(df2)
print("-" * 40)

# concat
# axis=0 垂直方向合并
result = pd.concat([df1, df2], axis=0, sort=True)
print(result)

print("-" * 40)

运行结果:

             A   B   C   D   E
2018-10-01   0   1   2   3   4
2018-10-02   5   6   7   8   9
2018-10-03  10  11  12  13  14
2018-10-04  15  16  17  18  19
----------------------------------------
            D  E   F   G
2018-10-03  0  1   2   3
2018-10-04  4  5   6   7
2018-10-05  8  9  10  11
----------------------------------------
               A     B     C   D   E     F     G
2018-10-01   0.0   1.0   2.0   3   4   NaN   NaN
2018-10-02   5.0   6.0   7.0   8   9   NaN   NaN
2018-10-03  10.0  11.0  12.0  13  14   NaN   NaN
2018-10-04  15.0  16.0  17.0  18  19   NaN   NaN
2018-10-03   NaN   NaN   NaN   0   1   2.0   3.0
2018-10-04   NaN   NaN   NaN   4   5   6.0   7.0
2018-10-05   NaN   NaN   NaN   8   9  10.0  11.0

axis=1水平方向合并:

# 上接
# axis=1 水平方向合并
result2 = pd.concat([df1, df2], axis=1)
print(result2)

运行结果:

               A     B     C     D     E    D    E     F     G
2018-10-01   0.0   1.0   2.0   3.0   4.0  NaN  NaN   NaN   NaN
2018-10-02   5.0   6.0   7.0   8.0   9.0  NaN  NaN   NaN   NaN
2018-10-03  10.0  11.0  12.0  13.0  14.0  0.0  1.0   2.0   3.0
2018-10-04  15.0  16.0  17.0  18.0  19.0  4.0  5.0   6.0   7.0
2018-10-05   NaN   NaN   NaN   NaN   NaN  8.0  9.0  10.0  11.0

说明:上面例子在进行垂直方向合并时,行索引出现了如图结果,此时可以通过ignore_index=True对数据合并后要求重新排序索引,默认不重新排序索引的。

image.png

ignore_index=True表示数据合并后重新排序索引,默认不重新排序索引:

# 上接
# 忽略索引
result3 = pd.concat([df1, df2], axis=0, ignore_index=True, sort=False)
print(result3)

运行结果:

      A     B     C   D   E     F     G
0   0.0   1.0   2.0   3   4   NaN   NaN
1   5.0   6.0   7.0   8   9   NaN   NaN
2  10.0  11.0  12.0  13  14   NaN   NaN
3  15.0  16.0  17.0  18  19   NaN   NaN
4   NaN   NaN   NaN   0   1   2.0   3.0
5   NaN   NaN   NaN   4   5   6.0   7.0
6   NaN   NaN   NaN   8   9  10.0  11.0

join="outer"或者"inner"outer表示向外括展,原来没有值得元素填充为NaN标记;inner表示向内收缩、取交集,只取公共行列的数据,其余的丢弃。join=默认取值outer

# 上接
# join=outer 默认
result4 = pd.concat([df1, df2], axis=0, join="outer", sort=False)
print(result4)

# join=inner
result5 = pd.concat([df1, df2], axis=0, join="inner", sort=False)
print(result5)

运行结果:

               A     B     C   D   E     F     G
2018-10-01   0.0   1.0   2.0   3   4   NaN   NaN
2018-10-02   5.0   6.0   7.0   8   9   NaN   NaN
2018-10-03  10.0  11.0  12.0  13  14   NaN   NaN
2018-10-04  15.0  16.0  17.0  18  19   NaN   NaN
2018-10-03   NaN   NaN   NaN   0   1   2.0   3.0
2018-10-04   NaN   NaN   NaN   4   5   6.0   7.0
2018-10-05   NaN   NaN   NaN   8   9  10.0  11.0

             D   E
2018-10-01   3   4
2018-10-02   8   9
2018-10-03  13  14
2018-10-04  18  19
2018-10-03   0   1
2018-10-04   4   5
2018-10-05   8   9
  • join_axes参数

join_axes=[df1.index或df1.columns]如果有join_axes的参数传入,可以指定根据那个轴来对齐数据。例如根据df1表对齐数据,就会保留指定的df1表的轴,然后将别的表与之拼接。

注意的是,此参数要和axis参数配合使用。如果axis=0,则如果有join_axes的参数传入,其值需要传入列索引才可以join_axes=[df1.columns]。反之,如果axis=1,则如果有join_axes的参数传入,其值需要传入行索引才可以join_axes=[df1.index]

# 上接
# axis=0, join_axes=[df1.columns]
result6 = pd.concat([df1, df2], axis=0, join_axes=[df1.columns], sort=False)
print(result6)

# axis=1, join_axes=[df1.index]
result7 = pd.concat([df1, df2], axis=1, join_axes=[df1.index], sort=False)
print(result7)

运行结果:

               A     B     C   D   E
2018-10-01   0.0   1.0   2.0   3   4
2018-10-02   5.0   6.0   7.0   8   9
2018-10-03  10.0  11.0  12.0  13  14
2018-10-04  15.0  16.0  17.0  18  19
2018-10-03   NaN   NaN   NaN   0   1
2018-10-04   NaN   NaN   NaN   4   5
2018-10-05   NaN   NaN   NaN   8   9

             A   B   C   D   E    D    E    F    G
2018-10-01   0   1   2   3   4  NaN  NaN  NaN  NaN
2018-10-02   5   6   7   8   9  NaN  NaN  NaN  NaN
2018-10-03  10  11  12  13  14  0.0  1.0  2.0  3.0
2018-10-04  15  16  17  18  19  4.0  5.0  6.0  7.0

说明:根据axis=, join_axes=[]入参不同,上面运行结果,分别保留了df1的列索引和行索引。

  • df.append()方式

df1.append([df2, df2, df3,...],axis=0或1,ignore_index=True)
参数说明:
[df1, df2, df3,...]表示要合并的多个DataFrame对象组成的列表;
axis=0或1分别表示在垂直方向合并还是在水平方向合并。
ignore_index=True表示数据合并后重新排序索引,默认不重新排序索引。

import pandas as pd
import numpy as np


# 数据的合并

index1 = pd.date_range("2018-10-01", periods=4)
df1 = pd.DataFrame(np.arange(20).reshape((4, 5)), index=index1, columns=list("ABCDE"))
print(df1)

print("-" * 40)

index2 = pd.date_range("2018-10-03", periods=3)
df2 = pd.DataFrame(np.arange(12).reshape((3, 4)), index=index2, columns=list("DEFG"))
print(df2)
print("-" * 40)


result8 = df1.append(df2, ignore_index=True, sort=False)
print(result8)

运行结果:

             A   B   C   D   E
2018-10-01   0   1   2   3   4
2018-10-02   5   6   7   8   9
2018-10-03  10  11  12  13  14
2018-10-04  15  16  17  18  19
----------------------------------------
            D  E   F   G
2018-10-03  0  1   2   3
2018-10-04  4  5   6   7
2018-10-05  8  9  10  11
----------------------------------------
      A     B     C   D   E     F     G
0   0.0   1.0   2.0   3   4   NaN   NaN
1   5.0   6.0   7.0   8   9   NaN   NaN
2  10.0  11.0  12.0  13  14   NaN   NaN
3  15.0  16.0  17.0  18  19   NaN   NaN
4   NaN   NaN   NaN   0   1   2.0   3.0
5   NaN   NaN   NaN   4   5   6.0   7.0
6   NaN   NaN   NaN   8   9  10.0  11.0

说明:df.append()函数的入参含义、用法和concat()含义一样,此处不再赘述。

  • pd.merge()方式

pd.merge(left, right, on=["key1", "key2"], how="inner", indicator="新索引说明")
参数说明:
left, right要参与合并的数据集;
on=["key1", "key2"]依据指定的key进行合并,可以有多个key
how="inner"或"outer"或"left"或"right"

left:完全保留left数据,并基于此数据,把其他数据合并过来。
right:完全保留right数据,并基于此数据,把其他数据合并过来。
indicator="新索引说明"合并的过程,通过自定义新索引的方式提示出来。

根据1个key合并"key",完整示例如下:

import pandas as pd

# 数据的合并

left = pd.DataFrame({
    "key": ["A0", "A1", "A2", "A3"],
    "B": ["B0", "B1", "B2", "B3"],
    "C": ["C0", "C1", "C2", "C3"],

})
print(left)

print("-" * 40)

right = pd.DataFrame({
    "key": ["A0", "A1", "A2", "A3"],
    "D": ["B1", "B2", "B2", "B4"],
    "E": ["C2", "C1", "C5", "C2"]

})
print(right)
print("-" * 40)
# 根据1个key合并"key"
result9 = pd.merge(left, right, on="key")
print(result9)

运行结果:

  key   B   C
0  A0  B0  C0
1  A1  B1  C1
2  A2  B2  C2
3  A3  B3  C3
--------------------
  key   D   E
0  A0  B1  C2
1  A1  B2  C1
2  A2  B2  C5
3  A3  B4  C2
--------------------
  key   B   C   D   E
0  A0  B0  C0  B1  C2
1  A1  B1  C1  B2  C1
2  A2  B2  C2  B2  C5
3  A3  B3  C3  B4  C2
  • 依据多个key的合并

on=["key1", "key2"]依据指定的key进行合并,可以有多个key。要注意的是,这里合并依据的列举出的key,一定要在要合并的数据表中确实存在才可以,否则会报错。

根据多个key合并,完整示例如下:

import pandas as pd

# 数据的合并

left = pd.DataFrame({
    "key": ["A0", "A1", "A2", "A3"],
    "B": ["B0", "B1", "B2", "B3"],
    "C": ["C0", "C1", "C2", "C3"],
})
print(left)

print("-" * 20)

right = pd.DataFrame({
    "key": ["A0", "A1", "A2", "A3"],
    "B": ["B0", "B2", "B2", "B4"],
    "E": ["C2", "C1", "C5", "C2"]

})
print(right)
print("-" * 20)

# 根据多个key合并"key", "B"
result9 = pd.merge(left, right, on=["key", "B"])

print(result9)

运行结果:

  key   B   C
0  A0  B0  C0
1  A1  B1  C1
2  A2  B2  C2
3  A3  B3  C3
--------------------
  key   B   E
0  A0  B0  C2
1  A1  B2  C1
2  A2  B2  C5
3  A3  B4  C2
--------------------
  key   B   C   E
0  A0  B0  C0  C2
1  A2  B2  C2  C5

说明:这里合并的依据on=["key", "B"],两个数据表匹配的上的只有两行数据,就是上面打印的结果。

  • 合并模式how=

how="inner"或"outer"或"left"或"right"

left:完全保留left数据,并基于此数据,把其他数据合并过来。
right:完全保留right数据,并基于此数据,把其他数据合并过来。示例如下:

# how=默认值
result9 = pd.merge(left, right, on=["key", "B"])
print(result9)

print("-" * 20)

# how="left"
result10 = pd.merge(left, right, on=["key", "B"], how="left")
print(result10)

print("-" * 20)

# how="right"
result11 = pd.merge(left, right, on=["key", "B"], how="right")
print(result11)

运行结果:

  key   B   C   E
0  A0  B0  C0  C2
1  A2  B2  C2  C5
--------------------
  key   B   C    E
0  A0  B0  C0   C2
1  A1  B1  C1  NaN
2  A2  B2  C2   C5
3  A3  B3  C3  NaN
--------------------
  key   B    C   E
0  A0  B0   C0  C2
1  A2  B2   C2  C5
2  A1  B2  NaN  C1
3  A3  B4  NaN  C2

数据的导出和导入

数据的导出和导入,支持多种格式csv、json、html等等,如下图:

导出选项

我们此处只随便选取2种举例,示例如下:

import pandas as pd

# 数据的导出和导入


left = pd.DataFrame({
    "key": ["A0", "A1", "A2", "A3"],
    "B": ["B0", "B1", "B2", "B3"],
    "C": ["C0", "C1", "C2", "C3"],

})

# 导出csv格式
left.to_csv("left_data.csv")

# 导出json格式
left.to_json("left.json")

运行结果:

导出为csv格式和json格式

说明:运行后,如果没有特别指定路径,则默认会在当前模块下生产对应的格式的文件。

数据画图

绘制图像,需要使用到matplotlib模块,绘图分为plt.plot(xxx)、plt.show()关键步骤。需要注意的是,此处我们可以直接用result.plot(),是因为result经过累加计算,已是数据了,可以直接用来绘制,然后调用plt.show()显示出图像即可。

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

# 生产1000个数据
s = pd.Series(np.random.randn(1000))

# 累加求和
result = s.cumsum()

# 绘制
result.plot()

# 显示图像
plt.show()

运行结果:


pandas绘图

小结

Pandas是基于NumPy的,两者是数据分析强大的工具。熟练掌握,对以后数据处理很有帮助。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 201,552评论 5 474
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,666评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 148,519评论 0 334
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,180评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,205评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,344评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,781评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,449评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,635评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,467评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,515评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,217评论 3 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,775评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,851评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,084评论 1 258
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,637评论 2 348
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,204评论 2 341

推荐阅读更多精彩内容