目录
一、简介
1、概念
Pandas (Python Data Analysis Library)是一个基于 NumPy 的数据分析工具,专为解决数据分析任务而创建。它汇集了大量库和一些标准的数据模型,可以更高效地操作大型数据集。
2、特点
- 数据结构: Pandas 提供了两种主要的数据结构,即 Series 和 DataFrame,用于处理一维和二维数据。
- 标签化: 数据结构带有标签,可以通过标签进行轴向操作,提高了数据操作的灵活性。
- 数据清洗: 提供了丰富的功能用于处理缺失值、重复项、异常值等,使数据更整洁。
- 数据操作: 支持各种数据操作,包括合并、连接、分组、聚合等,满足多种数据分析需求。
- 时间序列: 强大的时间序列处理功能,方便处理时间相关的数据。
3、引用
pip install pandas
import pandas as pd # 导入 Pandas 库并使用别名 pd
二、数据结构
1、Series
- 基本属性
values :返回底层的 NumPy 数组,包含 Series 中的数据。
index :返回索引对象,提供标签信息,用于标识每个数据点。
dtype :返回数据的数据类型,表示 Series 中存储的元素类型。
shape :返回数据的形状,对于一维数据,返回的是单元素元组。
size :返回数据的元素个数,表示 Series 中包含的数据点的数量。
nbytes :返回数据的字节大小,即存储数据所需的字节数。
ndim :返回数据的维度,对于 Series 来说,始终为1。
name :返回或设置 Series 的名称,可以用于标识 Series 对象的用途或含义。
python
import pandas as pd # 导入 Pandas 库并使用别名 pd
# 创建一个 Series 对象
s = pd.Series([1, 2, 3, 4, 5], name='my_series')
print(s.values) # [1 2 3 4 5]
print(s.index) # RangeIndex(start=0, stop=5, step=1)
print(s.dtype) # int64
print(s.shape) # (5,)
print(s.size) # 5
print(s.nbytes) # 40
print(s.ndim) # 1
print(s.name) # my_series
- 创建
python
import pandas as pd # 导入 Pandas 库并使用别名 pd
import numpy as np # 导入 NumPy 库并使用别名 np
# 从列表创建 Series
s1 = pd.Series([1, 2, 3, 4, 5])
print(s1)
# 0 1
# 1 2
# 2 3
# 3 4
# 4 5
# dtype: int64
# 从字典创建 Series
s2 = pd.Series({'a': 1, 'b': 2, 'c': 3})
print(s2)
# a 1
# b 2
# c 3
# dtype: int64
# 从 Numpy 数组创建 Series
s3 = pd.Series(np.array([1, 2, 3, 4, 5]))
print(s3)
# 0 1
# 1 2
# 2 3
# 3 4
# 4 5
# dtype: int32
# 从字典和标签列表创建 Series
s4 = pd.Series({'a': 1, 'b': 2, 'c': 3}, index=['a', 'b', 'c'])
print(s4)
# a 1
# b 2
# c 3
# dtype: int64
- 取值
python
import pandas as pd # 导入 Pandas 库并使用别名 pd
# 创建一个 Series 对象
s = pd.Series([1, 2, 3, 4, 5], index=['a', 'b', 'c', 'd', 'e'])
# 通过索引取值
value = s['b']
print(value) # 2
# 通过切片取值
slice_values = s['a':'c']
print(slice_values)
# a 1
# b 2
# c 3
# dtype: int64
# 取第二行
row_value = s.iloc[1]
print(row_value) # 2
2、DataFrame
- 基本属性
values :返回底层的 NumPy 数组,包含 DataFrame 中的数据。
columns :返回列名,表示 DataFrame 中每列的标签。
index :返回索引对象,提供标签信息,用于标识每行数据。
shape :返回数据的形状,是一个元组,表示DataFrame的行数和列数。
dtypes :返回每列的数据类型,表示 DataFrame 中存储的元素类型。
size :返回数据的元素个数,表示 DataFrame 中包含的数据点的总数量。
python
import pandas as pd # 导入 Pandas 库并使用别名 pd
# 创建一个 DataFrame 对象
data = {'name': ['Tom', 'Nick', 'John'], 'Age': [20, 21, 19]}
df = pd.DataFrame(data)
print(df.columns) # Index(['name', 'Age'], dtype='object')
print(df.index) # RangeIndex(start=0, stop=3, step=1)
print(df.values)
# [['Tom' 20]
# ['Nick' 21]
# ['John' 19]]
print(df.shape) # (3, 2)
print(df.dtypes)
# name object
# Age int64
# dtype: object
print(df.size) # 6
- 创建
python
import pandas as pd # 导入 Pandas 库并使用别名 pd
import numpy as np # 导入 NumPy 库并使用别名 np
# 创建一个字典
data = {'name': ['Tom', 'Nick', 'John', 'Tom'], 'Age': [20, 21, 19, 18]}
# 从字典创建 DataFrame
df = pd.DataFrame(data)
print(df)
# name Age
# 0 Tom 20
# 1 Nick 21
# 2 John 19
# 3 Tom 18
# 创建一个列表
data = [['Tom', 20], ['Nick', 21], ['John', 19], ['Tom', 18]]
# 从列表创建 DataFrame,指定列为'name'和'Age'
df = pd.DataFrame(data, columns=['name', 'Age'])
print(df)
# name Age
# 0 Tom 20
# 1 Nick 21
# 2 John 19
# 3 Tom 18
# 创建一个二维数组
data = np.array([['Tom', 20], ['Nick', 21], ['John', 19], ['Tom', 18]])
# 从二维数组创建 DataFrame,指定列为'name'和'Age'
df = pd.DataFrame(data, columns=['name', 'Age'])
print(df)
# name Age
# 0 Tom 20
# 1 Nick 21
# 2 John 19
# 3 Tom 18
# 创建一个 DataFrame,然后使用该 DataFrame 创建另一个 DataFrame
df1 = pd.DataFrame({'name': ['Tom', 'Nick', 'John'], 'Age': [20, 21, 19]})
df2 = pd.DataFrame(df1['name'], columns=['name']) # 使用 df1 的一个列创建新的 DataFrame
print(df2)
# name
# 0 Tom
# 1 Nick
# 2 John
# 添加一行
new_row = {'name': 'Alex', 'Age': 22}
# 使用 concat 方法将新行添加到 DataFrame,ignore_index=True 用于重置索引
df = pd.concat([df, pd.DataFrame([new_row])], ignore_index=True)
print(df)
# name Age
# 0 Tom 20
# 1 Nick 21
# 2 John 19
# 3 Tom 18
# 4 Alex 22
- 取值
python
import pandas as pd # 导入 Pandas 库并使用别名 pd
# 创建一个 DataFrame
data = {'Name': ['Tom', 'Nick', 'John', 'Peter'],'Age': [20, 21, 19, 18],'Score': [85, 80, 90, 88]}
df = pd.DataFrame(data)
# 通过列标签取值
# 选取单列
print(df['Name'])
# 0 Tom
# 1 Nick
# 2 John
# 3 Peter
# Name: Name, dtype: object
# 选取多列
print(df[['Name', 'Age']])
# Name Age
# 0 Tom 20
# 1 Nick 21
# 2 John 19
# 3 Peter 18
# 通过标签索引取值
# 设置行标签并选取行
df.index = ['Student1', 'Student2', 'Student3', 'Student4']
print(df.loc['Student1'])
# Name Tom
# Age 20
# Score 85
# Name: Student1, dtype: object
# 通过位置取值
# 选取第一行(索引为0)
print(df.iloc[0])
# Name Tom
# Age 20
# Score 85
# Name: Student1, dtype: object
# 使用布尔索引取值
# 选取年龄大于20的行
print(df[df['Age'] > 20])
# Name Age Score
# Student2 Nick 21 80
- 修改 index、columns
python
import pandas as pd # 导入 Pandas 库并使用别名 pd
data = {'name': ['Tom', 'Nick', 'John'], 'Age': [20, 21, 19]}
df = pd.DataFrame(data)
print(df)
# name Age
# 0 Tom 20
# 1 Nick 21
# 2 John 19
df.index = ['name', 'Age', 'height']
df.columns = ['Name', 'Age']
print(df)
# Name Age
# name Tom 20
# Age Nick 21
# height John 19
- 筛选
python
import pandas as pd # 导入 Pandas 库并使用别名 pd
import numpy as np # 导入 NumPy 库并使用别名 np
# 创建一个字典
data = {'name': ['Tom', 'Nick', 'John', 'Tom'], 'Age': [20, 21, 19, 18]}
# 从字典创建 DataFrame
df = pd.DataFrame(data)
print(df)
# name Age
# 0 Tom 20
# 1 Nick 21
# 2 John 19
# 3 Tom 18
# 根据条件筛选数据
filtered_df = df[df['Age'] > 20]
print(filtered_df)
# name Age
# 1 Nick 21
三、常见操作
1、数据合并
- concat
用于沿着一条轴(通常是行轴)连接两个或更多的对象。它不会改变轴标签。默认情况下,concat 沿着行方向(axis=0)连接对象。
python
import pandas as pd # 导入 Pandas 库并使用别名 pd
# 创建两个 DataFrame
df1 = pd.DataFrame({'A': ['A0', 'A1', 'A2'],
'B': ['B0', 'B1', 'B2'],
'C': ['C0', 'C1', 'C2'],
'D': ['D0', 'D1', 'D2']},
index=[0, 1, 2])
df2 = pd.DataFrame({'A': ['A3', 'A4', 'A5'],
'B': ['B3', 'B4', 'B5'],
'C': ['C3', 'C4', 'C5'],
'D': ['D3', 'D4', 'D5']},
index=[3, 4, 5])
result = pd.concat([df1, df2])
print(result)
# A B C D
# 0 A0 B0 C0 D0
# 1 A1 B1 C1 D1
# 2 A2 B2 C2 D2
# 3 A3 B3 C3 D3
# 4 A4 B4 C4 D4
# 5 A5 B5 C5 D5
- join
DataFrame 中的 join 方法用于将两个 DataFrame 连接在一起,连接是基于索引(行标签)进行的。
python
import pandas as pd # 导入 Pandas 库并使用别名 pd
# 创建两个 DataFrame
df1 = pd.DataFrame({'A': ['A0', 'A1', 'A2'],
'B': ['B0', 'B1', 'B2']},
index=[0, 1, 2])
df2 = pd.DataFrame({'C': ['C0', 'C1', 'C2'],
'D': ['D0', 'D1', 'D2']},
index=[0, 1, 2])
result = df1.join(df2, how='inner') # how='inner' 表示内连接,即只保留两个 DataFrame 中都有数据的行
print(result)
# A B C D
# 0 A0 B0 C0 D0
# 1 A1 B1 C1 D1
# 2 A2 B2 C2 D2
- merge
用于将两个 DataFrame 沿着一个或多个键(可以是行或列标签)进行连接,允许指定连接的键,可以进行左连接、右连接或外连接。
python
import pandas as pd # 导入 Pandas 库并使用别名 pd
# 创建两个 DataFrame
df1 = pd.DataFrame({'A': ['A0', 'A1', 'A2'],
'B': ['B0', 'B1', 'B2']},
index=[0, 1, 2])
df2 = pd.DataFrame({'C': ['C0', 'C1', 'C2'],
'D': ['D0', 'D1', 'D2']},
index=[0, 1, 3])
# left_index=True 表示进行左连接,即保留 df1 中的所有行,右连接同理。
# 默认情况下,两个 DataFrame 的索引都会被保留下来。
# 如果不想保留某个 DataFrame 的索引,可以使用 how='inner' 或 how='outer' 进行内连接或外连接。
result = pd.merge(df1, df2, left_index=True, right_index=True)
print(result)
# A B C D
# 0 A0 B0 C0 D0
# 1 A1 B1 C1 D1
2、数据删除
python
pandas.drop(labels=None, axis=0, index=None, columns=None, level=None, inpl
ace=False, errors='raise')
参数说明:
labels:要删除的行或列的标签。
axis:删除行还是列,0 或 'index' 代表行,1 或 'columns' 代表列。
index:要删除的行的索引。
columns:要删除的列的标签。
level:用于多层次索引(MultiIndex)的级别。
inplace:是否在原地修改 DataFrame。如果是 True,则直接在原 DataFrame 上进行修改,否则返回一个新的 DataFrame。
errors:如果尝试删除不存在的标签会引发什么错误,'raise' 表示引发错误,'ignore' 表示忽略。
python
import pandas as pd # 导入 Pandas 库并使用别名 pd
# 创建 DataFrame
df = pd.DataFrame({'A': [1, 2, 3], 'B': [4, 5, 6], 'C': [7, 8, 9]})
print(df)
# A B C
# 0 1 4 7
# 1 2 5 8
# 2 3 6 9
df.drop(columns='A', inplace=True)
print(df)
# B C
# 0 4 7
# 1 5 8
# 2 6 9
3、创建多层索引
使用 pd.MultiIndex.from_arrays() 方法创建多级索引对象。该方法接受两个列表作为参数,分别表示索引的级别。
python
import pandas as pd # 导入 Pandas 库并使用别名 pd
index = pd.MultiIndex.from_arrays([['A', 'A', 'B', 'B'], [1, 2, 1, 2]], names=['letters', 'numbers'])
df = pd.DataFrame({'col1': [10, 20, 30, 40]}, index=index)
print(df)
# col1
# letters numbers
# A 1 10
# 2 20
# B 1 30
# 2 40
result = df.loc['A'] # 选择第一级索引为 'A' 的数据
print(result)
# col1
# numbers
# 1 10
# 2 20
result = df.loc[('A', 2)] # 选择第一级索引为 'A',第二级索引为 2 的数据
print(result)
# col1 20
# Name: (A, 2), dtype: int64
4、数据对齐
python
import pandas as pd # 导入 Pandas 库并使用别名 pd
# 创建两个 Series 对象
s1 = pd.Series([1, 2, 3])
s2 = pd.Series([4, 5, 6])
# 算术运算
add_result = s1 + s2
print(add_result)
# 0 5
# 1 7
# 2 9
# dtype: int64
sub_result = s1 - s2
print(sub_result)
# 0 -3
# 1 -3
# 2 -3
# dtype: int64
mul_result = s1 * s2
print(mul_result)
# 0 4
# 1 10
# 2 18
# dtype: int64
div_result = s1 / s2
print(div_result)
# 0 0.25
# 1 0.40
# 2 0.50
# dtype: float64
5、排序
python
import pandas as pd # 导入 Pandas 库并使用别名 pd
# 创建一个 DataFrame
data = {'Name': ['Alice', 'Bob', 'Charlie'],
'Age': [25, 30, 22],
'Score': [90, 85, 88]}
df = pd.DataFrame(data)
# 显示原始 DataFrame
print(df)
# Name Age Score
# 0 Alice 25 90
# 1 Bob 30 85
# 2 Charlie 22 88
# 根据 'Score' 列的值进行排序
df_sorted_by_score = df.sort_values(by='Score', ascending=False)
print(df_sorted_by_score)
# Name Age Score
# 0 Alice 25 90
# 2 Charlie 22 88
# 1 Bob 30 85
# 根据索引进行排序
df_sorted_by_index = df.sort_index(ascending=False)
print(df_sorted_by_index)
# Name Age Score
# 2 Charlie 22 88
# 1 Bob 30 85
# 0 Alice 25 90
6、DataFrame 和 Series 之间的运算
python
import pandas as pd # 导入 Pandas 库并使用别名 pd
# 创建一个 DataFrame 和一个 Series
df = pd.DataFrame({'A': [1, 2], 'B': [3, 4]})
series = pd.Series([5, 6], index=['A', 'B'])
# 加法运算
add_result = df + series
print(add_result)
# A B
# 0 6 9
# 1 7 10
# 减法运算
subtract_result = df - series
print(subtract_result)
# A B
# 0 -4 -3
# 1 -3 -2
# 乘法运算
multiply_result = df * series
print(multiply_result)
# A B
# 0 5 18
# 1 10 24
# 除法运算
divide_result = df / series
print(divide_result)
# A B
# 0 0.2 0.500000
# 1 0.4 0.666667
四、应用
爬取天气数据并保存为 DataFrame 格式
python
import pandas as pd # 导入 pandas 库,用别名 pd
import requests # 导入 requests 模块,用于发送 HTTP 请求
from lxml import etree # 导入 lxml 中的 etree 模块,用于处理和解析 XML 数据
# 定义目标网址
url = 'https://weather.cma.cn/'
# 定义请求头,模拟浏览器访问
header = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36'
}
# 发送 HTTP GET 请求获取页面内容
res = requests.get(url, headers=header)
# 将获取的页面内容解码成 UTF-8 格式
content = res.content.decode('utf-8')
# 使用 etree.HTML 解析 HTML 内容
tree = etree.HTML(content)
# 从 HTML 树中提取所有 id 为 "HOT" 的 div 下的 a 标签
a_s = tree.xpath('//div[@id="HOT"]/a')
# 创建一个空列表用于存储提取的数据
lst = []
# 遍历除第一个外的所有 a 标签
for a in a_s[1:]:
# 创建一个空字典用于存储当前城市的信息
dic = {}
# 提取当前城市的排名信息,并去除首尾空格
dic['排名'] = a.xpath('./div[@class="rank"]/text()')[0].strip()
# 提取当前城市的名称信息,并去除首尾空格
dic['城市'] = a.xpath('./div[@class="sname"]/text()')[0].strip()
# 提取当前城市所属省份的信息,并去除首尾空格
dic['省份'] = a.xpath('./div[@class="pname"]/text()')[0].strip()
# 提取当前城市的最高温度信息,并去除首尾空格
dic['最高温度'] = a.xpath('./div[@class="value"]/text()')[0].strip()
# 将当前城市的信息字典添加到列表中
lst.append(dic)
# 打印最终提取的城市信息列表
print(lst)
# [{'排名': '1', '城市': '昌江', '省份': '海南', '最高温度': '29.9℃'}, {'排名': '2', '城市': '景洪', '省份': '云南', '最高温度': '29.7℃'}, {'排名': '3', '城市': '勐腊', '省份': '云南', '最高温度': '29℃'}, {'排名': '4', '城市': '保亭', '省份': '海南', '最高温度': '28.9℃'}, {'排名': '5', '城市': '乐东', '省份': '海南', '最高温度': '28.9℃'}, {'排名': '6', '城市': '白沙', '省份': '海南', '最高温度': '28.3℃'}, {'排名': '7', '城市': '巧家', '省份': '云南', '最高温度': '28.2℃'}, {'排名': '8', '城市': '东川', '省份': '云南', '最高温度': '28.1℃'}, {'排名': '9', '城市': '儋州', '省份': '海南', '最高温度': '27.7℃'}, {'排名': '10', '城市': '番禺', '省份': '广东', '最高温度': '27.6℃'}]
# 使用提取的数据创建 DataFrame
df = pd.DataFrame(lst)
# 打印 DataFrame
print(df)
# 排名 城市 省份 最高温度
# 0 1 昌江 海南 29.9℃
# 1 2 景洪 云南 29.7℃
# 2 3 勐腊 云南 29℃
# 3 4 保亭 海南 28.9℃
# 4 5 乐东 海南 28.9℃
# 5 6 白沙 海南 28.3℃
# 6 7 巧家 云南 28.2℃
# 7 8 东川 云南 28.1℃
# 8 9 儋州 海南 27.7℃
# 9 10 番禺 广东 27.6℃
记录学习过程,欢迎讨论交流,尊重原创,转载请注明出处~