什么是pandas
pandas
是python
的一个数据分析包,是基于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或1
:axis=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
对数据合并后要求重新排序索引,默认不重新排序索引的。
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")
运行结果:
说明:运行后,如果没有特别指定路径,则默认会在当前模块下生产对应的格式的文件。
数据画图
绘制图像,需要使用到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
是基于NumPy
的,两者是数据分析强大的工具。熟练掌握,对以后数据处理很有帮助。