Python零基础速成班-第17讲-Python for Pandas Series对象,DataFrame对象和性质,统计分析及排序运
学习目标
- Pandas Series对象
- Pandas DataFrame对象
- Pandas DataFrame性质
- Pandas 统计分析及排序运算
友情提示:将下文中代码拷贝到JupyterNotebook中直接执行即可,部分代码需要连续执行。
1、Pandas Series对象
1.1 Pandas 介绍:
- Pandas 是一种快速、强大、灵活且易于使用的开源数据分析和操作工具,构建在Python编程语言之上。
- Pandas 名字衍生自术语 “panel data”(面板数据)和 “Python data analysis”(Python 数据分析)。
- Pandas 一个强大的分析结构化数据的工具集,基础是 Numpy(提供高性能的矩阵运算)。
- Pandas 可以从各种文件格式比如 CSV、JSON、SQL、Microsoft Excel 导入数据。
- Pandas 可以对各种数据进行运算操作,比如归并、再成形、选择,还有数据清洗和数据加工特征。
- Pandas 广泛应用在学术、金融、统计学等各个数据分析领域。
1.2 安装并引入Pandas 包,Anaconda中自带该包
在线安装命令:pip install pandas 清华镜像安装:pip install -i https://pypi.tuna.tsinghua.edu.cn/simple pandas 引入相关包:import pandas as pd
1.3 Pandas 数据结构
- Pandas 的主要数据结构是 Series (一维数据)与 DataFrame(二维数据),这两种数据结构足以处理金融、统计、社会科学、工程等领域里的大多数典型用例。
- Series 是一种类似于一维数组的对象,它由一组数据(各种Numpy数据类型)以及一组与之相关的数据标签(即索引)组成。
- DataFrame 是一个表格型的数据结构,它含有一组有序的列,每列可以是不同的值类型(数值、字符串、布尔型值)。DataFrame 既有行索引也有列索引,它可以被看做由 Series 组成的字典(共同用一个索引)。
1.4 Pandas 部分优势:
- 处理浮点与非浮点数据里的缺失数据,表示为 NaN。
- 大小可变:插入或删除 DataFrame 等多维对象的列。
- 自动、显式数据对齐:显式地将对象与一组标签对齐,也可以忽略标签,在 Series、DataFrame 计算时自动与数据对齐。
- 强大、灵活的分组(group by)功能:拆分-应用-组合数据集,聚合、转换数据。
- 把 Python 和 NumPy 数据结构里不规则、不同索引的数据轻松地转换为 DataFrame 对象。
- 基于智能标签,对大型数据集进行切片、花式索引、子集分解等操作。
- 直观地合并(merge)、连接(join)数据集。
- 灵活地重塑(reshape)、透视(pivot)数据集。
- 轴支持结构化标签:一个刻度支持多个标签。
- 成熟的 IO 工具:读取文本文件(CSV 等支持分隔符的文件)、Excel 文件、数据库等来源的数据,利用超快的 HDF5 格式保存 / 加载数据。
- 时间序列:支持日期范围生成、频率转换、移动窗口统计、移动窗口线性回归、日期位移等时间序列功能。
1.5 Series对象的创建
Series是一种类似于以为NumPy数组的对象,它由一组数据(各种NumPy数据类型)和与之相关的一组数据标签(即索引)组成的。可以用index和values分别规定索引和值。如果不规定索引,会自动创建 0 到 N-1 索引。
语法: pd.Series(data, index=index, dtype=dtype)
- data:数据,可以是列表,字典或Numpy数组
- index:索引,为可选参数
- dtype: 数据类型,为可选参数
1.5.1 用list列表创建
import pandas as pd
s = pd.Series([1, 3, 5, np.nan, 6, 8])
print(s)
0 1.0
1 3.0
2 5.0
3 NaN
4 6.0
5 8.0
dtype: float64
加入索引和数据类型
import pandas as pd
data = pd.Series([1.5, 3, 4.5, 6], index=["a", "b", "c", "d"], dtype="float")
data
a 1.5
b 3.0
c 4.5
d 6.0
dtype: float64
支持多种数据格式
import pandas as pd
data = pd.Series([1, 2, "3", 4], index=["A", "B", "C", "D"])
print(data)
print("索引A值:",data['A']," 类型是:",type(data['A']))
print("索引C值:",data['C']," 类型是:",type(data['C']))
A 1
B 2
C 3
D 4
dtype: object
索引A值: 1 类型是: <class 'int'>
索引C值: 3 类型是: <class 'str'>
数据类型可被强制改变
import pandas as pd
data = pd.Series([1, 2, "3", 4], index=["a", "b", "c", "d"], dtype=float)
data
a 1.0
b 2.0
c 3.0
d 4.0
dtype: float64
1.5.2 用一维numpy数组创建
import pandas as pd
import numpy as np
pd.Series(np.arange(0,10,2),index=list('abcde'))
a 0
b 2
c 4
d 6
e 8
dtype: int32
1.5.3 用字典创建
默认以键为index 值为key
import pandas as pd
population_dict = {"BeiJing": 2154,
"ShangHai": 2424,
"ShenZhen": 1303,
"HangZhou": 981 }
pd.Series(population_dict)
BeiJing 2154
ShangHai 2424
ShenZhen 1303
HangZhou 981
dtype: int64
import pandas as pd
population = pd.Series(population_dict, index=["BeiJing", "HangZhou", "c", "d"])
population
BeiJing 2154.0
HangZhou 981.0
c NaN
d NaN
dtype: float64
2、Pandas DataFrame对象
DataFrame 是带标签数据的多维数组。可以理解为它是一种表格型结构,含有一组有序的列,每一列可以是不同的数据类型。既有行索引,又有列索引。
2.1 DataFrame对象的创建
语法: pd.DataFrame(data, index=index, columns=columns)
- data:数据,可以是列表,字典或Numpy数组
- index:索引,为可选参数
- columns: 列标签,为可选参数
2.1.1 通过Series对象创建,并加入列名
import pandas as pd
population_dict = {"BeiJing": 2154,
"ShangHai": 2424,
"ShenZhen": 1303,
"HangZhou": 981 }
population = pd.Series(population_dict)
pd.DataFrame(population,columns=["population"])
| population |
---|
BeiJing | 2154 |
---|
ShangHai | 2424 |
---|
ShenZhen | 1303 |
---|
HangZhou | 981 |
---|
2.1.2 通过Series对象字典创建,数据有缺失的会自动补齐为NaN
import pandas as pd
population_dict = {"BeiJing": 2154,
"ShangHai": 2424,
"ShenZhen": 1303,
"HangZhou": 981 }
GDP_dict = {"BeiJing": 30320,
"Chengdu": 32680,
"ShenZhen": 24222,
"HangZhou": 13468 }
population = pd.Series(population_dict)
GDP = pd.Series(GDP_dict)
pd.DataFrame({"population": population,"GDP": GDP,"country": "China"})
| population | GDP | country |
---|
BeiJing | 2154.0 | 30320.0 | China |
---|
Chengdu | NaN | 32680.0 | China |
---|
HangZhou | 981.0 | 13468.0 | China |
---|
ShangHai | 2424.0 | NaN | China |
---|
ShenZhen | 1303.0 | 24222.0 | China |
---|
2.1.3 通过字典列表对象创建
字典索引作为index,字典键作为columns
import pandas as pd
data = pd.DataFrame([{"num": i, "square": i**2} for i in range(1,5)])
print(data)
data1 = data["num"].copy()
print("复制某一列:\n",data1)
print("取某一个值:\n",data["square"][3])
num square
0 1 1
1 2 4
2 3 9
3 4 16
复制某一列:
0 1
1 2
2 3
3 4
Name: num, dtype: int64
取某一个值:
16
数据有缺失的会自动补齐为NaN
import pandas as pd
data = [{"a": 1, "b":1},{"b": 3, "c":4}]
pd.DataFrame(data)
2.1.4 通过Numpy二维数组创建
import pandas as pd
import numpy as np
data = np.random.randint(10, size=(3, 2))
pd.DataFrame(data, columns=["foo", "bar"], index=["a", "b", "c"])
3、Pandas DataFrame性质
3.1 DataFrame属性
import pandas as pd
population_dict = {"BeiJing": 2154,
"ShangHai": 2424,
"ShenZhen": 1303,
"HangZhou": 981 }
GDP_dict = {"BeiJing": 30320,
"Chengdu": 32680,
"ShenZhen": 24222,
"HangZhou": 13468 }
population = pd.Series(population_dict)
GDP = pd.Series(GDP_dict)
df = pd.DataFrame({"pop-column": population, "gdp-column": GDP})
df
| pop-column | gdp-column |
---|
BeiJing | 2154.0 | 30320.0 |
---|
Chengdu | NaN | 32680.0 |
---|
HangZhou | 981.0 | 13468.0 |
---|
ShangHai | 2424.0 | NaN |
---|
ShenZhen | 1303.0 | 24222.0 |
---|
df.values 返回numpy数组表示的数据
df.values
array([[ 2154., 30320.],
[ nan, 32680.],
[ 981., 13468.],
[ 2424., nan],
[ 1303., 24222.]])
df.index 返回行索引
df.index
Index(['BeiJing', 'Chengdu', 'HangZhou', 'ShangHai', 'ShenZhen'], dtype='object')
df.columns 返回列名
df.columns
Index(['pop-column', 'gdp-column'], dtype='object')
df.shape 返回数组形状
df.shape
(5, 2)
df.size 返回数组大小
df.size
10
df.dtypes 返回每列数据类型
df.dtypes
pop-column float64
gdp-column float64
dtype: object
3.2 DataFrame索引
import pandas as pd
population_dict = {"BeiJing": 2154,
"ShangHai": 2424,
"ShenZhen": 1303,
"HangZhou": 981 }
GDP_dict = {"BeiJing": 30320,
"Chengdu": 32680,
"ShenZhen": 24222,
"HangZhou": 13468 }
population = pd.Series(population_dict)
GDP = pd.Series(GDP_dict)
data = pd.DataFrame({"pop-column": population, "gdp-column": GDP})
data
| pop-column | gdp-column |
---|
BeiJing | 2154.0 | 30320.0 |
---|
Chengdu | NaN | 32680.0 |
---|
HangZhou | 981.0 | 13468.0 |
---|
ShangHai | 2424.0 | NaN |
---|
ShenZhen | 1303.0 | 24222.0 |
---|
3.2.1 获取列,data[“列名”]
data["pop-column"]
BeiJing 2154.0
Chengdu NaN
HangZhou 981.0
ShangHai 2424.0
ShenZhen 1303.0
Name: pop-column, dtype: float64
获取多列
data[["gdp-column", "pop-column"]]
| gdp-column | pop-column |
---|
BeiJing | 30320.0 | 2154.0 |
---|
Chengdu | 32680.0 | NaN |
---|
HangZhou | 13468.0 | 981.0 |
---|
ShangHai | NaN | 2424.0 |
---|
ShenZhen | 24222.0 | 1303.0 |
---|
3.2.2 通过行名获取行,data.loc[“索引名”]
data.loc["BeiJing"]
pop-column 2154.0
gdp-column 30320.0
Name: BeiJing, dtype: float64
通过行名获取多行
data.loc[["BeiJing", "HangZhou"]]
| pop-column | gdp-column |
---|
BeiJing | 2154.0 | 30320.0 |
---|
HangZhou | 981.0 | 13468.0 |
---|
3.2.3 通过索引获取行,data.iloc[索引]
data.iloc[0]
pop-column 2154.0
gdp-column 30320.0
Name: BeiJing, dtype: float64
通过索引获取多行
data.iloc[[1, 3]]
| pop-column | gdp-column |
---|
Chengdu | NaN | 32680.0 |
---|
ShangHai | 2424.0 | NaN |
---|
3.2.4 通过行列名获取坐标值(标量),data[“行名”,“列名”]
data.loc["BeiJing", "pop-column"]
2154.0
3.2.5 通过行列索引获取坐标值(标量),data[行索引,列索引] 或者通过data.values[行索引][列索引],两种方式均可
data.iloc[0, 1]
30320.0
data.values[0][1]
30320.0
3.3 DataFrame切片
通过Numpy二维数组创建一个DataFrame,索引为日期,列为ABCD,数据为随机24个数字。
import pandas as pd
import numpy as np
dates = pd.date_range(start='2019-01-01', periods=6)
df = pd.DataFrame(np.random.randn(6,4), index=dates, columns=["A", "B", "C", "D"])
df
| A | B | C | D |
---|
2019-01-01 | -1.329633 | 1.328714 | -1.654606 | 0.805278 |
---|
2019-01-02 | -0.495273 | -0.621967 | -0.301461 | 1.099235 |
---|
2019-01-03 | 0.001312 | -1.965503 | -1.007875 | -0.425179 |
---|
2019-01-04 | -1.242667 | 0.604385 | -0.690150 | 0.578622 |
---|
2019-01-05 | -1.044540 | -0.354231 | 1.394134 | 0.304671 |
---|
2019-01-06 | 0.325920 | -0.533395 | -0.515071 | 0.854837 |
---|
3.3.1 通过索引名对行切片,df[“索引名开始”: “索引名结束”]
df["2019-01-01": "2019-01-03"]
| A | B | C | D |
---|
2019-01-01 | -1.329633 | 1.328714 | -1.654606 | 0.805278 |
---|
2019-01-02 | -0.495273 | -0.621967 | -0.301461 | 1.099235 |
---|
2019-01-03 | 0.001312 | -1.965503 | -1.007875 | -0.425179 |
---|
3.3.2 通过绝对索引对行切片,df.loc[“索引名开始”: “索引名结束”]
df.loc["2019-01-01": "2019-01-03"]
| A | B | C | D |
---|
2019-01-01 | -1.329633 | 1.328714 | -1.654606 | 0.805278 |
---|
2019-01-02 | -0.495273 | -0.621967 | -0.301461 | 1.099235 |
---|
2019-01-03 | 0.001312 | -1.965503 | -1.007875 | -0.425179 |
---|
3.3.3 通过相对索引对行切片,df.iloc[索引开始: 索引结束]
df.iloc[0: 2]
| A | B | C | D |
---|
2019-01-01 | -1.329633 | 1.328714 | -1.654606 | 0.805278 |
---|
2019-01-02 | -0.495273 | -0.621967 | -0.301461 | 1.099235 |
---|
3.3.4 通过列名对列切片,df.loc[:, “列名开始”: “列名结束”]
df.loc[:, "A": "C"]
| A | B | C |
---|
2019-01-01 | -1.329633 | 1.328714 | -1.654606 |
---|
2019-01-02 | -0.495273 | -0.621967 | -0.301461 |
---|
2019-01-03 | 0.001312 | -1.965503 | -1.007875 |
---|
2019-01-04 | -1.242667 | 0.604385 | -0.690150 |
---|
2019-01-05 | -1.044540 | -0.354231 | 1.394134 |
---|
2019-01-06 | 0.325920 | -0.533395 | -0.515071 |
---|
3.3.4 通过列索引对列切片,df.loc[:, “列名索引开始”: “列名索引结束”]
df.iloc[:, 0: 3]
| A | B | C |
---|
2019-01-01 | -1.329633 | 1.328714 | -1.654606 |
---|
2019-01-02 | -0.495273 | -0.621967 | -0.301461 |
---|
2019-01-03 | 0.001312 | -1.965503 | -1.007875 |
---|
2019-01-04 | -1.242667 | 0.604385 | -0.690150 |
---|
2019-01-05 | -1.044540 | -0.354231 | 1.394134 |
---|
2019-01-06 | 0.325920 | -0.533395 | -0.515071 |
---|
3.3.5 多样化取值(行列同时切片),df.loc[“索引名开始”:“索引名结束”, “列名开始”: “列名结束”]
df.loc["2019-01-02": "2019-01-03", "C":"D"]
| C | D |
---|
2019-01-02 | -0.301461 | 1.099235 |
---|
2019-01-03 | -1.007875 | -0.425179 |
---|
3.3.6 多样化取值(行列同时切片),df.iloc[“索引开始”:“索引结束”, “列索引开始”: “列索引结束”]
df.iloc[1: 3, 2:]
| C | D |
---|
2019-01-02 | -0.301461 | 1.099235 |
---|
2019-01-03 | -1.007875 | -0.425179 |
---|
3.3.7 多样化取值,df.loc[[“索引名”,“索引名”…], [“列名”, “列名”…]]
df.loc[["2019-01-02", "2019-01-06"], ["C","D"]]
| C | D |
---|
2019-01-02 | -0.301461 | 1.099235 |
---|
2019-01-06 | -0.515071 | 0.854837 |
---|
3.3.8 多样化取值,df.iloc[[“索引”,“索引”…], [“列索引”, “列索引”…]]
df.iloc[[1, 5], [0, 3]]
| A | D |
---|
2019-01-02 | -0.495273 | 1.099235 |
---|
2019-01-06 | 0.325920 | 0.854837 |
---|
3.3.9 混合多样化取值
df.loc["2019-01-04": "2019-01-06", ["A", "C"]]
| A | C |
---|
2019-01-04 | -1.242667 | -0.690150 |
---|
2019-01-05 | -1.044540 | 1.394134 |
---|
2019-01-06 | 0.325920 | -0.515071 |
---|
df.iloc[3:, [0, 2]]
| A | C |
---|
2019-01-04 | -1.242667 | -0.690150 |
---|
2019-01-05 | -1.044540 | 1.394134 |
---|
2019-01-06 | 0.325920 | -0.515071 |
---|
3.4 DataFrame布尔索引
import pandas as pd
import numpy as np
dates = pd.date_range(start='2019-01-01', periods=6)
df = pd.DataFrame(np.random.randn(6,4), index=dates, columns=["A", "B", "C", "D"])
df
| A | B | C | D |
---|
2019-01-01 | 0.996569 | 1.578279 | 0.463043 | -0.672513 |
---|
2019-01-02 | 1.020281 | -1.131021 | -0.142832 | -0.212521 |
---|
2019-01-03 | 0.819800 | -0.138255 | 0.617334 | 0.613512 |
---|
2019-01-04 | -0.436693 | -0.607578 | -0.032253 | 0.578040 |
---|
2019-01-05 | 0.485066 | -0.504814 | 1.578476 | 0.244499 |
---|
2019-01-06 | -2.069133 | -0.291120 | -0.037155 | 0.280606 |
---|
判断数据 > 0,是则True,否则False
df > 0
| A | B | C | D |
---|
2019-01-01 | True | True | True | False |
---|
2019-01-02 | True | False | False | False |
---|
2019-01-03 | True | False | True | True |
---|
2019-01-04 | False | False | False | True |
---|
2019-01-05 | True | False | True | True |
---|
2019-01-06 | False | False | False | True |
---|
将df > 0的数据取出来
df[df > 0]
| A | B | C | D |
---|
2019-01-01 | 0.996569 | 1.578279 | 0.463043 | NaN |
---|
2019-01-02 | 1.020281 | NaN | NaN | NaN |
---|
2019-01-03 | 0.819800 | NaN | 0.617334 | 0.613512 |
---|
2019-01-04 | NaN | NaN | NaN | 0.578040 |
---|
2019-01-05 | 0.485066 | NaN | 1.578476 | 0.244499 |
---|
2019-01-06 | NaN | NaN | NaN | 0.280606 |
---|
判断A列 > 0,是则True,否则False
df.A > 0
2019-01-01 True
2019-01-02 True
2019-01-03 True
2019-01-04 False
2019-01-05 True
2019-01-06 False
Freq: D, Name: A, dtype: bool
输入A列 > 0的数据
df[df.A > 0]
| A | B | C | D |
---|
2019-01-01 | 0.996569 | 1.578279 | 0.463043 | -0.672513 |
---|
2019-01-02 | 1.020281 | -1.131021 | -0.142832 | -0.212521 |
---|
2019-01-03 | 0.819800 | -0.138255 | 0.617334 | 0.613512 |
---|
2019-01-05 | 0.485066 | -0.504814 | 1.578476 | 0.244499 |
---|
拷贝数据并增加一列
df2 = df.copy()
df2['E'] = ['one', 'one', 'two', 'three', 'four', 'three']
df2
| A | B | C | D | E |
---|
2019-01-01 | 0.996569 | 1.578279 | 0.463043 | -0.672513 | one |
---|
2019-01-02 | 1.020281 | -1.131021 | -0.142832 | -0.212521 | one |
---|
2019-01-03 | 0.819800 | -0.138255 | 0.617334 | 0.613512 | two |
---|
2019-01-04 | -0.436693 | -0.607578 | -0.032253 | 0.578040 | three |
---|
2019-01-05 | 0.485066 | -0.504814 | 1.578476 | 0.244499 | four |
---|
2019-01-06 | -2.069133 | -0.291120 | -0.037155 | 0.280606 | three |
---|
isin( )方法表示接受一个列表,判断该列中元素是否在列表中。
ind = df2["E"].isin(["two", "four"])
ind
2019-01-01 False
2019-01-02 False
2019-01-03 True
2019-01-04 False
2019-01-05 True
2019-01-06 False
Freq: D, Name: E, dtype: bool
将满足条件的行数据取出来
df2[ind]
| A | B | C | D | E |
---|
2019-01-03 | 0.819800 | -0.138255 | 0.617334 | 0.613512 | two |
---|
2019-01-05 | 0.485066 | -0.504814 | 1.578476 | 0.244499 | four |
---|
3.5 DataFrame赋值
import pandas as pd
import numpy as np
dates = pd.date_range(start='2019-01-01', periods=3)
df = pd.DataFrame(np.random.randn(3,4), index=dates, columns=["A", "B", "C", "D"])
s1 = pd.Series([1, 2, 3, 4], index=pd.date_range('20190101', periods=4))
s1
2019-01-01 1
2019-01-02 2
2019-01-03 3
2019-01-04 4
Freq: D, dtype: int64
将整列数据根据索引 index赋值到 DataFrame中
注意,index不一致的将不会被赋值填充,如下例,"2019-01-04 4"的数据将不会被填充到数组中
df["E"] = s1
df
| A | B | C | D | E |
---|
2019-01-01 | -0.760792 | -0.031330 | -1.079199 | -0.566817 | 1 |
---|
2019-01-02 | -0.265456 | 1.877067 | -2.560142 | 0.529421 | 2 |
---|
2019-01-03 | -1.481884 | 0.399466 | 0.947172 | 0.117282 | 3 |
---|
根据行名和列名对坐标位置赋值
df.loc["2019-01-01", "A"] = 0
df
| A | B | C | D | E |
---|
2019-01-01 | 0.000000 | -0.031330 | -1.079199 | -0.566817 | 1 |
---|
2019-01-02 | -0.265456 | 1.877067 | -2.560142 | 0.529421 | 2 |
---|
2019-01-03 | -1.481884 | 0.399466 | 0.947172 | 0.117282 | 3 |
---|
根据行索引和列索引对坐标位置赋值,如下列为第1行第2列
df.iloc[0, 1] = 1
df
| A | B | C | D | E |
---|
2019-01-01 | 0.000000 | 1.000000 | -1.079199 | -0.566817 | 1 |
---|
2019-01-02 | -0.265456 | 1.877067 | -2.560142 | 0.529421 | 2 |
---|
2019-01-03 | -1.481884 | 0.399466 | 0.947172 | 0.117282 | 3 |
---|
将某列整体赋值为统一值
df["D"] = np.array([5]*len(df))
df
| A | B | C | D | E |
---|
2019-01-01 | 0.000000 | 1.000000 | -1.079199 | 5 | 1 |
---|
2019-01-02 | -0.265456 | 1.877067 | -2.560142 | 5 | 2 |
---|
2019-01-03 | -1.481884 | 0.399466 | 0.947172 | 5 | 3 |
---|
修改 index
df.index = [i for i in range(len(df))]
df
| A | B | C | D | E |
---|
0 | 0.000000 | 1.000000 | -1.079199 | 5 | 1 |
---|
1 | -0.265456 | 1.877067 | -2.560142 | 5 | 2 |
---|
2 | -1.481884 | 0.399466 | 0.947172 | 5 | 3 |
---|
修改 columns,df.shape[0] 表示二维数组的行数,df.shape[1] 表示二维数组的列数
df.columns = [i for i in range(df.shape[1])]
df
| 0 | 1 | 2 | 3 | 4 |
---|
0 | 0.000000 | 1.000000 | -1.079199 | 5 | 1 |
---|
1 | -0.265456 | 1.877067 | -2.560142 | 5 | 2 |
---|
2 | -1.481884 | 0.399466 | 0.947172 | 5 | 3 |
---|
4、Pandas 统计分析及排序运算
4.1 数据的查看
import pandas as pd
import numpy as np
dates = pd.date_range(start='2019-01-01', periods=6)
df = pd.DataFrame(np.random.randn(6,4), index=dates, columns=["A", "B", "C", "D"])
df
| A | B | C | D |
---|
2019-01-01 | -0.806471 | 1.123945 | -0.516413 | 0.197803 |
---|
2019-01-02 | -1.946585 | -0.214416 | -1.009902 | -1.310953 |
---|
2019-01-03 | 0.516981 | 0.533711 | 1.281586 | -1.251843 |
---|
2019-01-04 | -0.323077 | -0.907300 | 1.298455 | 0.359652 |
---|
2019-01-05 | 0.512790 | -0.225682 | -1.547499 | -0.293725 |
---|
2019-01-06 | -0.764418 | 0.799160 | -0.360248 | -0.075538 |
---|
查看前面的行,默认5行
df.head()
| A | B | C | D |
---|
2019-01-01 | -0.806471 | 1.123945 | -0.516413 | 0.197803 |
---|
2019-01-02 | -1.946585 | -0.214416 | -1.009902 | -1.310953 |
---|
2019-01-03 | 0.516981 | 0.533711 | 1.281586 | -1.251843 |
---|
2019-01-04 | -0.323077 | -0.907300 | 1.298455 | 0.359652 |
---|
2019-01-05 | 0.512790 | -0.225682 | -1.547499 | -0.293725 |
---|
df.head(2)
| A | B | C | D |
---|
2019-01-01 | -0.806471 | 1.123945 | -0.516413 | 0.197803 |
---|
2019-01-02 | -1.946585 | -0.214416 | -1.009902 | -1.310953 |
---|
查看后面的行,默认5行
df.tail(3)
| A | B | C | D |
---|
2019-01-04 | -0.323077 | -0.907300 | 1.298455 | 0.359652 |
---|
2019-01-05 | 0.512790 | -0.225682 | -1.547499 | -0.293725 |
---|
2019-01-06 | -0.764418 | 0.799160 | -0.360248 | -0.075538 |
---|
查看总体信息
主要介绍数据集各列的数据类型,是否为空值,内存占用情况
df.info()
<class 'pandas.core.frame.DataFrame'>
DatetimeIndex: 6 entries, 2019-01-01 to 2019-01-06
Freq: D
Data columns (total 4 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 A 6 non-null float64
1 B 6 non-null float64
2 C 6 non-null float64
3 D 5 non-null float64
dtypes: float64(4)
memory usage: 240.0 bytes
4.2 Numpy通用函数同样适用于Pandas
import pandas as pd
import numpy as np
x = pd.DataFrame(np.arange(11,15).reshape(1, 4))
x
向量化运算
x+5
np.exp(x)
| 0 | 1 | 2 | 3 |
---|
0 | 59874.141715 | 162754.791419 | 442413.392009 | 1.202604e+06 |
---|
import pandas as pd
import numpy as np
y = pd.DataFrame(np.arange(4,8).reshape(1, 4))
y
元素相乘,即按位相乘
x*y
import pandas as pd
import numpy as np
np.random.seed(42)
x1 = pd.DataFrame(np.random.randint(10, size=(4, 4)),columns=["a","b","c","d"],index=np.arange(1,5))
x1
转置
z = x1.T
z
import pandas as pd
import numpy as np
np.random.seed(1)
y1 = pd.DataFrame(np.random.randint(10, size=(4, 4)),columns=["a","b","c","d"],index=np.arange(1,5))
y1
矩阵相乘,即A @ B或者A.dot(B)
import pandas as pd
import numpy as np
np.random.seed(3)
c = pd.DataFrame(np.random.randint(5, size=(2, 2)))
c
import pandas as pd
import numpy as np
np.random.seed(4)
d = pd.DataFrame(np.random.randint(5, size=(2, 2)))
d
c.dot(d)
使用%timeit查询矩阵相乘的效率
%timeit c.dot(d)
115 μs ± 16.8 μs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
%timeit np.dot(c, d)
34 μs ± 10.1 μs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
执行相同运算,Numpy与Pandas的对比 一般来说,纯粹的计算在Numpy里执行的更快 Numpy更侧重于计算,Pandas更侧重于数据处理
4.3 索引对齐
import pandas as pd
import numpy as np
A = pd.DataFrame(np.random.randint(0, 10, size=(2, 2)), columns=list("AB"))
A
import pandas as pd
import numpy as np
B = pd.DataFrame(np.random.randint(0, 10, size=(3, 3)), columns=list("ABC"))
B
pandas会自动对齐两个对象的索引,没有的值用np.nan表示
A+B
| A | B | C |
---|
0 | 9.0 | 12.0 | NaN |
---|
1 | 12.0 | 13.0 | NaN |
---|
2 | NaN | NaN | NaN |
---|
缺省值也可用fill_value来填充(将补集填充到数组中), fill_value=0即为补集值+0,fill_value=0即为补集值+1
A.add(B, fill_value=0)
| A | B | C |
---|
0 | 9.0 | 12.0 | 1.0 |
---|
1 | 12.0 | 13.0 | 4.0 |
---|
2 | 2.0 | 3.0 | 4.0 |
---|
4.4 去重及统计
import pandas as pd
import numpy as np
e = np.random.randint(3, size=8)
e
array([1, 2, 2, 0, 2, 2, 1, 0])
去重复
np.unique(e)
array([0, 1, 2])
f = pd.DataFrame(e, columns=["A"])
f
np.unique(f)
array([0, 1, 2])
统计列名出现的次数
from collections import Counter
Counter(f)
Counter({'A': 1})
统计A列每个元素出现次数
f["A"].value_counts()
2 4
1 2
0 2
Name: A, dtype: int64
4.5 排序运算
import pandas as pd
import numpy as np
population_dict = {"BeiJing": 2154,
"ShangHai": 2424,
"ShenZhen": 1303,
"HangZhou": 981 }
population = pd.Series(population_dict)
GDP_dict = {"BeiJing": 30320,
"ShangHai": 32680,
"ShenZhen": 24222,
"HangZhou": 13468 }
GDP = pd.Series(GDP_dict)
city_info = pd.DataFrame({"population": population,"GDP": GDP})
city_info
| population | GDP |
---|
BeiJing | 2154 | 30320 |
---|
ShangHai | 2424 | 32680 |
---|
ShenZhen | 1303 | 24222 |
---|
HangZhou | 981 | 13468 |
---|
将运算结果写入新的列中
city_info["per_GDP"] = city_info["GDP"]/city_info["population"]
city_info
| population | GDP | per_GDP |
---|
BeiJing | 2154 | 30320 | 14.076137 |
---|
ShangHai | 2424 | 32680 | 13.481848 |
---|
ShenZhen | 1303 | 24222 | 18.589409 |
---|
HangZhou | 981 | 13468 | 13.728848 |
---|
递增排序,语法:data.sort_values(by=“排序字段”,ascending=True(默认))
city_info.sort_values(by="per_GDP",ascending=True)
| population | GDP | per_GDP |
---|
ShangHai | 2424 | 32680 | 13.481848 |
---|
HangZhou | 981 | 13468 | 13.728848 |
---|
BeiJing | 2154 | 30320 | 14.076137 |
---|
ShenZhen | 1303 | 24222 | 18.589409 |
---|
递减排序,语法:data.sort_values(by=“排序字段”,ascending=False)
city_info.sort_values(by="per_GDP", ascending=False)
| population | GDP | per_GDP |
---|
ShenZhen | 1303 | 24222 | 18.589409 |
---|
BeiJing | 2154 | 30320 | 14.076137 |
---|
HangZhou | 981 | 13468 | 13.728848 |
---|
ShangHai | 2424 | 32680 | 13.481848 |
---|
import pandas as pd
import numpy as np
data = pd.DataFrame(np.random.randint(20, size=(3, 4)), index=[2, 1, 0], columns=list("CBAD"))
data
行排序,语法:data.sort_index()
data.sort_index()
列排序,语法:data.sort_index(axis=1)
data.sort_index(axis=1)
列降序排列
data.sort_index(axis=1, ascending=False)
4.6 统计方法
import pandas as pd
import numpy as np
df = pd.DataFrame(np.random.normal(2, 4, size=(6, 4)),columns=list("ABCD"))
df
| A | B | C | D |
---|
0 | -1.299184 | -4.238557 | 2.461770 | 2.820545 |
---|
1 | 1.506934 | 1.498438 | -1.720567 | 2.962674 |
---|
2 | 2.234540 | -0.008980 | 4.007714 | 1.154215 |
---|
3 | 3.474472 | 8.359345 | 2.622616 | 2.630422 |
---|
4 | -1.119273 | 1.073369 | -2.657330 | -2.986037 |
---|
5 | -1.788804 | 5.545772 | 0.881042 | -1.186639 |
---|
统计每一列非空个数,语法:df.count()
df.count()
A 6
B 6
C 6
D 6
dtype: int64
按列求和(跨行),语法:df.sum()
df.sum()
A 3.008684
B 12.229387
C 5.595246
D 5.395181
dtype: float64
按行求和(跨列),语法:df.sum(axis=1)
df.sum(axis=1)
0 -0.255426
1 4.247479
2 7.387489
3 17.086856
4 -5.689272
5 3.451372
dtype: float64
列最小值(跨行),语法:df.min()
df.min()
A -1.788804
B -4.238557
C -2.657330
D -2.986037
dtype: float64
行最大值(跨列),语法:df.max(axis=1)
df.max(axis=1)
0 2.820545
1 2.962674
2 4.007714
3 8.359345
4 1.073369
5 5.545772
dtype: float64
列最大值(跨行)的index,语法:df.idxmax()
df.idxmax()
A 3
B 3
C 2
D 1
dtype: int64
求列平均值(跨行),语法:df.mean()
df.mean()
A 0.501447
B 2.038231
C 0.932541
D 0.899197
dtype: float64
求行平均值(跨列),语法:df.mean(axis=1)
df.mean(axis=1)
0 -0.063856
1 1.061870
2 1.846872
3 4.271714
4 -1.422318
5 0.862843
dtype: float64
求列方差(跨行),语法:df.var()
df.var()
A 4.793550
B 19.414161
C 6.916080
D 6.091489
dtype: float64
求列标准差(跨行),语法:df.std()
df.std()
A 2.189418
B 4.406150
C 2.629844
D 2.468094
dtype: float64
求列中位数(跨行),语法:df.median()
df.median()
A 0.193830
B 1.285903
C 1.671406
D 1.892319
dtype: float64
将DataFrame对象转化为Numpy数组对象,语法:df.to_numpy()
df.to_numpy()
array([[-1.29918381, -4.2385569 , 2.46177046, 2.82054459],
[ 1.50693372, 1.49843756, -1.72056689, 2.96267444],
[ 2.23453984, -0.00898034, 4.00771412, 1.15421545],
[ 3.47447198, 8.35934524, 2.62261641, 2.63042244],
[-1.11927344, 1.0733692 , -2.65733046, -2.98603696],
[-1.78880426, 5.54577214, 0.88104242, -1.18663862]])
介绍数据集各列的数据统计情况(最大值、最小值、标准偏差、分位数等等),语法:df.describe()
df.describe()
| A | B | C | D |
---|
count | 6.000000 | 6.000000 | 6.000000 | 6.000000 |
---|
mean | 0.501447 | 2.038231 | 0.932541 | 0.899197 |
---|
std | 2.189418 | 4.406150 | 2.629844 | 2.468094 |
---|
min | -1.788804 | -4.238557 | -2.657330 | -2.986037 |
---|
25% | -1.254206 | 0.261607 | -1.070165 | -0.601425 |
---|
50% | 0.193830 | 1.285903 | 1.671406 | 1.892319 |
---|
75% | 2.052638 | 4.533938 | 2.582405 | 2.773014 |
---|
max | 3.474472 | 8.359345 | 4.007714 | 2.962674 |
---|
5、上一讲Python零基础速成班-第16讲-Python for Matplotlib 线图、散点图、柱形图、饼图 课后作业及答案
1、完成一个简单的单线条图满足以下要求:
公式:
f
(
x
)
=
s
i
n
2
(
x
?
2
)
e
?
x
2
f(x) = sin^2(x - 2)e^{ -x^2}
f(x)=sin2(x?2)e?x2
要求:
- 将[0,2]等分30次写入x轴,使用上述公式得出y轴值
- 标题为公式(公式显示用法请自行搜索),X轴label为 asis-X,Y轴label为 asis-Y
- 线条样式要求:黑色、破折线、粗细2
- 其他样式要求:X轴Y轴标签单独定义font:均为darkred色,字体大小15,X轴标签左对齐,Y轴标签靠上对齐
- 加入灰色网格线,粗细1,垂直于x轴
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(0,2,30)
y = (np.sin(x-2))**2 * np.exp(-(x**2))
plt.plot(x,y,'k--',linewidth=2)
fontaxis = {"color":"darkred","size":15}
plt.xlabel("asis-X",fontdict=fontaxis,loc="left")
plt.ylabel("asix-Y",fontdict=fontaxis,loc="top")
plt.title("$ f(x) = sin^2(x - 2)e^{ -x^2} $")
plt.grid(color="grey",linewidth=1,axis="x")
plt.show()
2、完成一个简单的多线条图满足以下要求:
- 将[0,2]等分100次写入x轴,y轴分别为x,x平方,x立方
- 在一张画布中展示出三个线条x(蓝色),x平方(橙色),x立方(绿色)
- 三条曲线图例标题"linear",“quadratic”,“cubic”
- x轴命名x-label,y轴命名y-label,标题为Simple Plot,画布大小8 * 5
提示:
- 使用plt.figure(figsize=(8,5))定义画布大小
- 使用plt.legend()显示图例标题
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(0,2,100)
plt.figure(figsize=(8,5))
plt.plot(x,x,label="linear",color="blue")
plt.plot(x,x**2,label="quadratic",color="orange")
plt.plot(x,x**3,label="cubic",color="green")
plt.xlabel("x-label")
plt.ylabel("y-label")
plt.title("Simple Plot")
plt.legend()
plt.show()
3、使用面向对象写法fig,ax =plt.subplots()绘制多图满足以下要求:
- 完成一个2行1列子画布图形上下展示,画布整体大小8 * 8,上图数据来源于x,y和x,w,下图数据来源于x,z,整体共享x轴
- x轴为[0,0.5]按0.01递增的数组,y轴为公式
c
o
s
(
2
?
π
?
x
)
cos(2 * \pi * x)
cos(2?π?x),z轴为range(len(x)),w轴为公式
c
o
s
(
1.5
?
π
?
x
)
cos(1.5 * \pi * x)
cos(1.5?π?x)
- 上图中x,y图例标题为2pi,x,w图例标题为1.5pi,下图中线条颜色为红色
提示:
- 子画布可以使用fig,ax = subplots(),ax[0],ax[1],ax[3]…的方式展现或fig,(ax1,ax2,ax3…) = subplots(),ax1,ax2,ax3…的方式展现
- 定义画布大小可以在plt.subplots()中使用figsize=(m,n)参数
- 显示图例仍然使用legend()
import matplotlib.pyplot as plt
import numpy as np
x = np.arange(0.0,5,0.01)
y = np.cos(2*np.pi*x)
z = np.array(range(len(x)))
w = np.cos(1.5*np.pi*x)
fig,ax=plt.subplots(2,1,figsize=(8,8),sharex=True)
ax[0].plot(x,y,label="2pi")
ax[0].plot(x,w,label="1.5pi")
ax[0].legend()
ax[1].plot(x,z,color ="red")
plt.show()
4、使用面向对象写法fig,ax =plt.subplots()绘制多图满足以下要求:
- 完成一个1行2列子画布图形左右展示,左图为线图,右图为散点图,画布整体大小10 * 4,数据data1~4来源于4组0-1随机取样100个
- 左图直接输出四组数据,分别使用点状o、菱形d、倒三角v、正方形s,显示图例标题data1 data2 data3 data4,标题为My Plot
- 右图x轴为data1,y轴为data2,颜色为data3(0-100),大小为data4(0-900),透明度0.4,需要输出渐变色条,标题为My Scatter
提示:
- 数据定义可以使用data1, data2, data3, data4 = np.random.rand(4, 100)
- 左图画布输出可以使用ax1.plot(data1,“o”,label=“data1”) ax2.plot(data2,“d”,label=“data2”)…
- 右图颜色定义可以使用colors = data3 * 100,大小定义可以使用sizes = (data4 * 30) ** 2
- 右图画布输出可以使用ax2array = ax2.scatter(data1,data2,s=sizes,c=colors)
- 输出渐变色条可以使用fig.colorbar(ax2array)
import numpy as np
import matplotlib.pyplot as plt
data1, data2, data3, data4 = np.random.rand(4, 100)
fig,(ax1,ax2) = plt.subplots(1,2,figsize=(10,4))
ax1.plot(data1,"o",label="data1")
ax1.plot(data2,"d",label="data2")
ax1.plot(data3,"v",label="data3")
ax1.plot(data4,"s",label="data4")
ax1.legend()
ax1.set_title("My Plot")
colors = data3*100
sizes = (data4*30)**2
ax2array = ax2.scatter(data1,data2,s=sizes,c=colors)
fig.colorbar(ax2array)
ax2.set_title("My Scatter")
plt.show()
5、完成A公司销售数据柱状图满足以下要求:
-
销售数据为 data = {‘Barton LLC’: 109438.50, ‘Frami, Hills and Schmidt’: 103569.59, ‘Fritsch, Russel and Anderson’: 112214.71, ‘Jerde-Hilpert’: 112591.43, ‘Keeling LLC’: 100934.30, ‘Koepp Ltd’: 103660.54, ‘Kulas Inc’: 137351.96, ‘Trantow-Barrows’: 123381.38, ‘White-Trantow’: 135841.99, ‘Will LLC’: 104437.60} -
横向,x轴为销售额,y轴为分公司名 销售额 group_data = list(data.values()) 分公司名 group_names = list(data.keys()) 销售平均值 group_mean = np.mean(group_data) -
标题为Company Revenue -
显示平均线,红色,虚线 -
分公司名为’Jerde-Hilpert’,‘Koepp Ltd’,'White-Trantow’的在y轴右侧显示注释文本"New Comany"
提示:
- 平均线设置可以使用plt.axvline(group_mean,color=“red”,linestyle=“–”)
- 在y轴右侧显示注释文本可以使用下列语法:
for group in [3,5,8]: plt.text(145000,group,“New Company”)
import matplotlib.pyplot as plt
import numpy as np
data = {'Barton LLC': 109438.50,
'Frami, Hills and Schmidt': 103569.59,
'Fritsch, Russel and Anderson': 112214.71,
'Jerde-Hilpert': 112591.43,
'Keeling LLC': 100934.30,
'Koepp Ltd': 103660.54,
'Kulas Inc': 137351.96,
'Trantow-Barrows': 123381.38,
'White-Trantow': 135841.99,
'Will LLC': 104437.60}
group_data = list(data.values())
group_names = list(data.keys())
group_mean = np.mean(group_data)
plt.barh(group_names,group_data)
plt.title("Company Revenue")
plt.axvline(group_mean,color="red",linestyle="--")
for group in [3,5,8]:
plt.text(145000,group,"New Company")
plt.show()
6、完成西南5省2021GDP饼状图满足以下要求:
-
GDP数据为 data = {‘四川省’: 53850, ‘重庆市’: 27894, ‘云南省’: 27146, ‘贵州省’: 19568, ‘西藏自治区’: 2000} -
省份及gdp province = list(data.keys()) gdp = list(data.values()) -
饼状图标签为省份名字,标题为"西南5省2021GDP统计" -
输出百分比%.2f%%,重庆市突出显示,突出距离0.1 -
字体均为黑体
提示:
- 设置全局字体可使用 plt.rcParams[‘font.family’]=[‘SimHei’]
import matplotlib.pyplot as plt
import numpy as np
data = {'四川省': 53850,
'重庆市': 27894,
'云南省': 27146,
'贵州省': 19568,
'西藏自治区': 2000
}
gdp = list(data.values())
province = list(data.keys())
plt.rcParams['font.family']=['SimHei']
plt.pie(gdp,
labels=province,
explode=(0,0.1,0,0,0),
autopct="%.2f%%"
)
plt.title("西南5省2021GDP统计")
plt.show()
|