目录
1、pandas 常用类
1.1 Series
1.1.1创建 Series
1.1.2 访问 Series 数据
1.1.3 更新、插入和删除
1.2 DataFrame
1.2.1 创建 DataFrame
1.2.2 访问DataFrame首尾数据
1.2.3 更新、插入和删除(列操作)
1.3 Index
1.3.1 创建 Index
1.3.2 常用方法
2、DataFrame 基础操作
2.1 索引
2.1.1 基础化索引
2.1.2 loc 方法和 iloc方法(行、列操作)
2.1.3 行追加append
2.1.4 删除数据行
2.1.5 MultiIndex
2.2 排序
2.2.1 sort_index 方法
2.2.2 sort_values 方法
2.3 合并
2.3.1 堆叠合并
3、时间数据
3.1 Python 模块time
3.1.1 time模块
3.1.2 datetime 模块
3.1.3 timedelta 类,时间加减
3.2 Pandas 时间 Timedelta
3.3 Pandas 时间转化 to_datetime
3.4 Pandas 时间序列 date_range
Series 由一组数据以及一组与之对应的数据标签(即索引)组成。Series 对象可以视作一个NumPy 的 ndarray ,因此许多NumPy库函数可以作用于 series。
Pandas Series 类似表格中的一个列(column),类似于一维数组,可以保存任何数据类型,本质上是一个 ndarray。Series 由索引(index)和列组成,函数如下:
pandas.Series( data=None, index=None, dtype=None, name=None, copy=False)
参数说明:
data:一组数据(ndarray 类型)。
index:数据索引标签,如果不指定,默认从 0 开始。
dtype:数据类型,默认会自己判断。
name:设置该 Series 名称。
copy:拷贝数据,默认为 False。仅影响 Series 和 ndarray 数组
通过 ndarray 创建 Series
import numpy as np
import pandas as pd
print('通过 ndarray 创建的 Series 为:\n', pd.Series(np.arange(5), index=['a', 'b', 'c', 'd', 'e'], name='ndarray'))
运行结果:
通过 ndarray 创建的 Series 为:
a 0
b 1
c 2
d 3
e 4
Name: ndarray, dtype: int32
若数据存放在 dict 中,则可以通过 dict 创建 Series,此时 dict 的键名(key)作为 Series 的索引,其值会作为 Series 的值,因此无需传入 index 参数。通过dict创建 Series 对象,代码如下:
通过 dict 创建 Series
import numpy as np
import pandas as pd
dit = {'a': 0, 'b': 1, 'c': 2, 'd': 3}
print('通过 dict 创建的 Series 为:\n', pd.Series(dit))
运行结果:
通过 dict 创建的 Series 为:
a 0
b 1
c 2
d 3
dtype: int64
通过 list 创建 Series
import numpy as np
import pandas as pd
list1 = [1, 2, 3, 4, 5]
list2 = [10, 2, 36, 4, 25]
print('通过 list 创建的 Series 为:\n', pd.Series(list1)) # 索引为默认
print('通过 list 创建的 Series 为:\n', pd.Series(list2, index=['a', 'b', 'c', 'd', 'e'], name='list'))
运行结果:
通过 list 创建的 Series 为:
0 1
1 2
2 3
3 4
4 5
dtype: int64
通过 list 创建的 Series 为:
a 10
b 2
c 36
d 4
e 25
Name: list, dtype: int64
属性 | 说明 |
values | 以 ndarray 的格式返回 Series 对象的所有元素 |
index | 返回 Series 对象的索引 |
dtype | 返回 Series 对象的数据类型 |
shape | 返回 Series 对象的形状 |
nbytes | 返回 Series 对象的字节数 |
ndim | 返回 Series 对象的维度 |
size | 返回 Series 对象的个数 |
T | 返回 Series 对象的转置 |
axes | 返回 Series 索引列表 |
import numpy as np
import pandas as pd
list1 = [1, 2, 3, 4, 5]
series = pd.Series(list1, index=['a', 'b', 'c', 'd', 'e'], name='list')
print('通过 dict 创建的 Series 为:\n', series)
print('数组形式返回 Series 为:', series.values)
print('Series 的 Index 为:', series.index)
print('Series 的 形状为:', series.shape)
print('Series 的 维度为:', series.ndim)
print('Series 对象的个数为:', series.size)
print('返回 Series 索引列表为:', series.axes)
运行结果:
通过 dict 创建的 Series 为:
a 1
b 2
c 3
d 4
e 5
Name: list, dtype: int64
数组形式返回 Series 为: [1 2 3 4 5]
Series 的 Index 为: Index(['a', 'b', 'c', 'd', 'e'], dtype='object')
Series 的 形状为: (5,)
Series 的 维度为: 1
Series 对象的个数为: 5
返回 Series 索引列表为: [Index(['a', 'b', 'c', 'd', 'e'], dtype='object')]
索引和切片是 Series 最常用的操作之一,通过索引位置访问 Series 的数据与 ndarray 相同。Series 使用标签切片时,其末端时包含的,使用位置数值切片,其末端是不包含的。
import numpy as np
import pandas as pd
# 创建 Series
s1 = pd.Series(np.arange(1, 6))
print('通过 ndarray 创建的 Series 为:\n', s1) # 索引为默认
print(f"s1.index为:\n{s1.index}")
print(f"s1.index强制转换为列表输出为:\n{list(s1.index)}")
# 通过标签取得对应的值,或进行修改
s1[2] = 100
# print(s1[-1]) # 无法通过反向索引
s1[-1] = 99 # 新增一行数据
print(f"现在的Series为:\n{s1}")
print(f"s1[-1]: {s1[-1]}") # 标签中存在-1
运行结果:
通过 ndarray 创建的 Series 为:
0 1
1 2
2 3
3 4
4 5
dtype: int32
s1.index为:
RangeIndex(start=0, stop=5, step=1)
s1.index强制转换为列表输出为:
[0, 1, 2, 3, 4]
现在的Series为:
0 1
1 2
2 100
3 4
4 5
-1 99
dtype: int64
s1[-1]: 99
import numpy as np
import pandas as pd
dit = {'a': 0, 'b': 1, 'c': 2, 'd': 3}
print('通过 dict 创建的 Series 为:\n', pd.Series(dit))
# 通过标签取得相应的值,或进行修改
dit['s'] = 9
print(f"dit['b'] = {dit['b']}")
运行结果:
通过 dict 创建的 Series 为:
a 0
b 1
c 2
d 3
dtype: int64
dit['b'] = 1
import numpy as np
import pandas as pd
list1 = [1, 2, 3, 4, 5]
series = pd.Series(list1, index=['a', 'b', 'c', 'd', 'e'], name='list')
print('通过 dict 创建的 Series 为:\n', series)
print(f"Series 位于第 1 位置的数据为:{series[0]}")
# 通过索引名称(标签)也可以访问Series 数据
print(f"Series中 Index 为 ‘b’的数据为:{series['b']}")
print(f"bool 类型的 Series 为:\n{series < 4}")
print(f"通过bool 数组访问Series 为:\n{series[series < 4]}")
运行结果:
通过 dict 创建的 Series 为:
a 1
b 2
c 3
d 4
e 5
Name: list, dtype: int64
Series 位于第 1 位置的数据为:1
Series中 Index 为 ‘b’的数据为:2
bool 类型的 Series 为:
a True
b True
c True
d False
e False
Name: list, dtype: bool
通过bool 数组访问Series 为:
a 1
b 2
c 3
Name: list, dtype: int64
import numpy as np
import pandas as pd
list1 = [1, 2, 3, 4, 5]
series = pd.Series(list1, index=['a', 'b', 'c', 'd', 'e'], name='list')
print('通过 dict 创建的 Series 为:\n', series)
# 更新元素
series['b'] = 9
print(f"更新后的 Series 为:\n{series}")
# 在原 Series 上插入(追加)新的Series
series1 = pd.Series([4, 5], index=['f', 'g'])
# 追加
print(f"在 series 后插入 series1,结果为:\n{series.append(series1)}")
# 添加单个元素
series1['h'] = 7
print(f"插入单个数据后 series1:\n{series1}")
# 删除 Series 元素
series.drop('e', inplace=True)
print('删除索引 e 对应的数据后的 series 为:\n', series)
运行结果:
通过 dict 创建的 Series 为:
a 1
b 2
c 3
d 4
e 5
Name: list, dtype: int64
更新后的 Series 为:
a 1
b 9
c 3
d 4
e 5
Name: list, dtype: int64
在 series 后插入 series1,结果为:
a 1
b 9
c 3
d 4
e 5
f 4
g 5
dtype: int64
插入单个数据后 series1:
f 4
g 5
h 7
dtype: int64
删除索引 e 对应的数据后的 series 为:
a 1
b 9
c 3
d 4
Name: list, dtype: int64
DataFrame 是 pandas 基本数据结构,类似于数据库中的表。 DataFrame 既有行索引,也有列索引,它可以看作 Series 组成的 dict ,每个 Series 看作 DataFrame 的一个列。
DataFrame 函数用于创建 DataFrame 对象,其基本语法格式如下:
class pandas.DataFrame(data, index, columns, dtype, copy)
参数名称 | 说明 |
data | 接收 ndarray、dict、list或DataFrame,表示输入数据。默认为None |
index | 接收Index、ndarray,表示索引。默认为 None。 |
columns | 接收Index、ndarray,表示列标签(列名)。默认为None |
创建 DataFrame 的方法由很多,常见的一种是传入一个由等长 list 或 ndarray 组成的 dict。
若没有传入 columns 参数,则传入的 dict 的键会被当做列名。
使用字典创建 DataFrame 对象
import numpy as np
import pandas as pd
# 通过 dict 创建 DataFrame
dict1 = {'col1': [0, 1, 2, 3, 4], 'col2': [5, 6, 7, 8, 9]}
print(f"痛过 dict 创建的 DataFrame 为:\n{pd.DataFrame(dict1,index=['a', 'b', 'c', 'd', 'e'])}")
# 通过 list 创建 DataFrame
list2 = [[0, 5, 1], [1, 6, 5], [2, 6, 3], [8, 9, 5], [8, 3, 4]]
print(f"痛过 list 创建的 DataFrame 为:\n{pd.DataFrame(list2,index=['a', 'b', 'c', 'd', 'e'], columns=['col1', 'col2', 'col3'])}")
运行结果:
痛过 dict 创建的 DataFrame 为:
col1 col2
a 0 5
b 1 6
c 2 7
d 3 8
e 4 9
痛过 list 创建的 DataFrame 为:
col1 col2 col3
a 0 5 1
b 1 6 5
c 2 6 3
d 8 9 5
e 8 3 4
使用嵌套列表创建:
import numpy as np
import pandas as pd
data = [['xiaoming', 20], ['lina', 35], ['jam', 24]]
# 未分配列标签
df = pd.DataFrame(data)
print('使用嵌套列表创建的 DataFrame(未分配列标签) 为:\n', df)
# 分配列标签
df1 = pd.DataFrame(data, columns=['name', 'Age'])
print('使用嵌套列表创建的 DataFrame(分配列标签) 为:\n', df1)
运行结果:
使用嵌套列表创建的 DataFrame(未分配列标签) 为:
0 1
0 xiaoming 20
1 lina 35
2 jam 24
使用嵌套列表创建的 DataFrame(分配列标签) 为:
name Age
0 xiaoming 20
1 lina 35
2 jam 24
使用列表嵌套字典创建 DataFrame 对象
import numpy as np
import pandas as pd
data = [{'a': 1, 'b': 2}, {'a': 5, 'b': 10, 'c': 20}]
df = pd.DataFrame(data, index=['first', 'second'])
# 如果其中某个元素值缺失,也就是字典的key无法找到对应的 value ,将使用 NaN 代替
print(f"列表嵌套字典创建 DataFrame 对象:\n{df}")
运行结果:
列表嵌套字典创建 DataFrame 对象:
a b c
first 1 2 NaN
second 5 10 20.0
使用 Series 创建 DataFrame 对象
import numpy as np
import pandas as pd
data = {'one': pd.Series([1, 2, 3], index=['a', 'b', 'c']),
'two': pd.Series([1, 2, 3, 4], index=['a', 'b', 'c', 'd'])}
df = pd.DataFrame(data)
# 对于 one 列而言,此处虽然显示了行索引'd',但由于没有与其对应的值,所以它的值为 NaN
print(f"通过 Series 创建 DataFrame 对象:\n{df}")
运行结果:
通过 Series 创建 DataFrame 对象:
one two
a 1.0 1
b 2.0 2
c 3.0 3
d NaN 4
属性 | 说明 |
T | 行列转置 |
columns | 返回 DataFrame 的列标签 |
dtypes | 返回 DataFrame 各列的数据类型 |
index | 返回行索引名 |
shape | 返回 DataFrame 对象的形状 |
size | 返回 DataFrame 对象包含的元素个数 |
values | 以 ndarray 的格式返回 DataFrame 对象的所有元素 |
loc | 通过行索引获取行数据 |
iloc | 通过行号获取数据 |
axes | 返回一个仅以行轴标签和列轴标签为成员的列表 |
empty | DataFrame 中没有数据或者任意坐标轴的长度为0,则返回True |
head() | 返回前 n 行数据 |
tail() | 返回后 n 行数据 |
rename() | rename(columns=字典),修改列名 |
info() | 可以显示信息,例如行/列数,总内存使用量,每列的数据类型以及 |
import numpy as np
import pandas as pd
# 设置打印宽度,使打印数据对齐
pd.set_option('display.unicode.ambiguous_as_wide', True)
pd.set_option('display.unicode.east_asian_width', True)
df = pd.DataFrame({'city': ['上海市', '北京市', '广州市', '深圳市'], 'GDP': [13908.57, 12406.8, 9891.48, 9709.02]},
columns=['city', 'GDP'])
print(f"通过 dict 创建的 DataFrame 为:\n{df}")
print(f" DataFrame 的转置为:\n{df.T}")
print(f"查看行索引名为:\n{df.index}")
print(f"查看行列索引名为:\n{df.columns}")
print(f"查看 DataFrame 的形状为:\n{df.shape}")
print(f"查看 DataFrame 对象的数据为:\n{df.values}")
print(f"查看 DataFrame 指定列df['GDP']的内容为:\n{df['GDP']}")
print(f"查看 DataFrame 指定列df.GDP的内容为:\n{df.GDP}")
print(f"查看 DataFrame 行号为 2 这一行内容为:\n{df.loc[2]}")
print(f"查看 DataFrame 元素个数:\n{df.size}")
运行结果:
通过 dict 创建的 DataFrame 为:
city GDP
0 上海市 13908.57
1 北京市 12406.80
2 广州市 9891.48
3 深圳市 9709.02
DataFrame 的转置为:
0 1 2 3
city 上海市 北京市 广州市 深圳市
GDP 13908.57 12406.8 9891.48 9709.02
查看行索引名为:
RangeIndex(start=0, stop=4, step=1)
查看行列索引名为:
Index(['city', 'GDP'], dtype='object')
查看 DataFrame 的形状为:
(4, 2)
查看 DataFrame 对象的数据为:
[['上海市' 13908.57]
['北京市' 12406.8]
['广州市' 9891.48]
['深圳市' 9709.02]]
查看 DataFrame 指定列df['GDP']的内容为:
0 13908.57
1 12406.80
2 9891.48
3 9709.02
Name: GDP, dtype: float64
查看 DataFrame 指定列df.GDP的内容为:
0 13908.57
1 12406.80
2 9891.48
3 9709.02
Name: GDP, dtype: float64
查看 DataFrame 行号为 2 这一行内容为:
city 广州市
GDP 9891.48
Name: 2, dtype: object
查看 DataFrame 元素个数:
8
修改列标签名 rename() 和 info()函数的用法
import pandas as pd
data = {
'Name': ['关羽', '刘备', '张飞', '曹操'],
'Age': [28, 34, 29, 42],
"Salary": [5000, 8000, 4500, 10000]
}
df = pd.DataFrame(data)
print(f"原始 DataFrame 为:\n{df}")
# 修改列标签名
df1 = df.rename(columns={'Name': 'name', 'Age': 'age'})
print(f"修改列标签名后的 DataFrame df1 为:\n{df1}")
print(f"修改列标签名后的 DataFrame df 为:\n{df}")
# 添加inplace参数,修改原数据
df.rename(index={1: 'row2', 2: 'row3'}, columns={'Name': 'name', 'Age': 'age'}, inplace=True)
print(f"添加inplace参数,修改原数据后的 DataFrame df 为:\n{df}")
print(f'df.info() :\n{df.info()}')
运行结果:
原始 DataFrame 为:
Name Age Salary
0 关羽 28 5000
1 刘备 34 8000
2 张飞 29 4500
3 曹操 42 10000
修改列标签名后的 DataFrame df1 为:
name age Salary
0 关羽 28 5000
1 刘备 34 8000
2 张飞 29 4500
3 曹操 42 10000
修改列标签名后的 DataFrame df 为:
Name Age Salary
0 关羽 28 5000
1 刘备 34 8000
2 张飞 29 4500
3 曹操 42 10000
添加inplace参数,修改原数据后的 DataFrame df 为:
name age Salary
0 关羽 28 5000
row2 刘备 34 8000
row3 张飞 29 4500
3 曹操 42 10000
Index: 4 entries, 0 to 3
Data columns (total 3 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 name 4 non-null object
1 age 4 non-null int64
2 Salary 4 non-null int64
dtypes: int64(2), object(1)
memory usage: 128.0+ bytes
df.info() :
None
head 和 tail 方法用于访问 DataFrame 前 n 行和后 n 行数据,默认返回 5 行数据。
import pandas as pd
# 通过 list 创建 DataFrame
list2 = [[0, 5, 1], [1, 6, 5], [2, 6, 3], [8, 9, 5], [8, 3, 4], [5, 6, 2]]
dict2 = pd.DataFrame(list2,index=['a', 'b', 'c', 'd', 'e', 'f'], columns=['col1', 'col2', 'col3'])
print(f"痛过 list 创建的 DataFrame 为:\n{dict2}")
print('默认返回前 5 行数据为:\n', dict2.head())
print('返回后 3 行数据为:\n', dict2.tail(3))
运行结果:
痛过 list 创建的 DataFrame 为:
col1 col2 col3
a 0 5 1
b 1 6 5
c 2 6 3
d 8 9 5
e 8 3 4
f 5 6 2
默认返回前 5 行数据为:
col1 col2 col3
a 0 5 1
b 1 6 5
c 2 6 3
d 8 9 5
e 8 3 4
返回后 3 行数据为:
col1 col2 col3
d 8 9 5
e 8 3 4
f 5 6 2
选取 DataFrame 列
可以使用列索引,轻松实现数据选取
import numpy as np
import pandas as pd
data = {'Name': ['关羽', '刘备', '张飞', '曹操'], 'Age': [28, 34, 29, 42]}
# 定义行标签
index = ["rank1", "rank2", "rank3", "rank4"]
# 通过字典创建 DataFrame
df = pd.DataFrame(data, index=index)
print(f"创建 DataFrame 对象:\n{df}")
# 取出指定列
print(f"取出Name 列:\n{df['Name']}")
# 取出指定多列(两层中括号)
print(f"取出Name、Age 列:\n{df[['Name', 'Age']]}")
# 不能进行切片选取多列 print(df['Name':'Age']) 错误!!!
# 不能通过标签去获取列 print(df[1]) 错误!!!
运行结果:
创建 DataFrame 对象:
Name Age
rank1 关羽 28
rank2 刘备 34
rank3 张飞 29
rank4 曹操 42
取出Name 列:
rank1 关羽
rank2 刘备
rank3 张飞
rank4 曹操
Name: Name, dtype: object
取出Name、Age 列:
Name Age
rank1 关羽 28
rank2 刘备 34
rank3 张飞 29
rank4 曹操 42
DataFrame 列的添加
①使用 columns 列索引标签可以实现添加新的数据列
import numpy as np
import pandas as pd
data = {'one': pd.Series([1, 2, 3], index=['a', 'b', 'c']),
'two': pd.Series([1, 2, 3, 4], index=['a', 'b', 'c', 'd'])}
df = pd.DataFrame(data)
# 对于 one 列而言,此处虽然显示了行索引'd',但由于没有与其对应的值,所以它的值为 NaN
print(f"通过 Series 创建 DataFrame 对象:\n{df}")
# 添加列
df['three'] = pd.Series([10, 20, 30], index=['a', 'b', 'c'])
# 将已存在的数据列相加运算,从而创建一个新的列
df['four'] = df['one'] + df['three']
print(f"最后 DataFrame 的结果为:\n{df}")
运行结果:
通过 Series 创建 DataFrame 对象:
one two
a 1.0 1
b 2.0 2
c 3.0 3
d NaN 4
最后 DataFrame 的结果为:
one two three four
a 1.0 1 10.0 11.0
b 2.0 2 20.0 22.0
c 3.0 3 30.0 33.0
d NaN 4 NaN NaN
② 采用 insert() 方法添加列
import numpy as np
import pandas as pd
data = {'one': pd.Series([1, 2, 3], index=['a', 'b', 'c']),
'two': pd.Series([1, 2, 3, 4], index=['a', 'b', 'c', 'd'])}
df = pd.DataFrame(data)
# 对于 one 列而言,此处虽然显示了行索引'd',但由于没有与其对应的值,所以它的值为 NaN
print(f"通过 Series 创建 DataFrame 对象:\n{df}")
# 添加列, 数值 1 表插入到 columns 列表的索引位置
df.insert(1, column='five', value=[10, 20, 30, 40])
print(f"最后 DataFrame 的结果为:\n{df}")
运行结果:
通过 Series 创建 DataFrame 对象:
one two
a 1.0 1
b 2.0 2
c 3.0 3
d NaN 4
最后 DataFrame 的结果为:
one five two
a 1.0 10 1
b 2.0 20 2
c 3.0 30 3
d NaN 40 4
更新 DataFrame 列
类似 Series ,更新 DataFrame 列也采用赋值的方法,对指定列赋值。
import pandas as pd
# 通过 list 创建 DataFrame
list2 = [[0, 5, 1], [1, 6, 5], [2, 6, 3], [8, 9, 5], [8, 3, 4], [5, 6, 2]]
dict2 = pd.DataFrame(list2,index=['a', 'b', 'c', 'd', 'e', 'f'], columns=['col1', 'col2', 'col3'])
print(f"通过 list 创建的 DataFrame 为:\n{dict2}")
# 更新列
dict2['col1'] = [10, 11, 12, 13, 14, 15]
print(f"更新列后 DataFrame 为:\n{dict2}")
# 插入列
dict2['col4'] = [100, 111, 102, 103, 141, 151]
print(f"插入列后 DataFrame 为:\n{dict2}")
运行结果:
通过 list 创建的 DataFrame 为:
col1 col2 col3
a 0 5 1
b 1 6 5
c 2 6 3
d 8 9 5
e 8 3 4
f 5 6 2
更新列后 DataFrame 为:
col1 col2 col3
a 10 5 1
b 11 6 5
c 12 6 3
d 13 9 5
e 14 3 4
f 15 6 2
插入列后 DataFrame 为:
col1 col2 col3 col4
a 10 5 1 100
b 11 6 5 111
c 12 6 3 102
d 13 9 5 103
e 14 3 4 141
f 15 6 2 151
删除 DataFrame 列
删除列的方法有很多中,如 del、pop、drop等。常用的是 drop 方法,它可以删除行或列。基本语法格式如下
DataFrame.drop(labels, axis=0, level=None, inplace=False, errors = 'raise')
参数名称 | 说明 |
labels | 接收string或array,表示删除行或列的标签。无默认值 |
axis | 接收0或1,其中0表示删除行,1表示删除列。默认为0 |
levels | 接收int或者索引名,表示索引级别。默认为None |
inplace | 接收 bool,表示操作是否对原数据生效。默认为False |
import pandas as pd
# 通过 list 创建 DataFrame
list2 = [[0, 5, 1], [1, 6, 5], [2, 6, 3], [8, 9, 5], [8, 3, 4], [5, 6, 2]]
dict2 = pd.DataFrame(list2,index=['a', 'b', 'c', 'd', 'e', 'f'], columns=['col1', 'col2', 'col3'])
print(f"通过 list 创建的 DataFrame 为:\n{dict2}")
# 删除列
dict2.drop(['col3'], axis=1, inplace=True)
print('删除 col3 列后的 DataFrame 为:\n', dict2)
# 删除行
dict2.drop('a', axis=0, inplace=True)
print('删除 a 行后的 DataFrame 为:\n', dict2)
运行结果:
通过 list 创建的 DataFrame 为:
col1 col2 col3
a 0 5 1
b 1 6 5
c 2 6 3
d 8 9 5
e 8 3 4
f 5 6 2
删除 col3 列后的 DataFrame 为:
col1 col2
a 0 5
b 1 6
c 2 6
d 8 9
e 8 3
f 5 6
删除 a 行后的 DataFrame 为:
col1 col2
b 1 6
c 2 6
d 8 9
e 8 3
f 5 6
Index 对象为其余 pandas 对象存储轴标签、管理轴标签和其他元数据(如轴名称)。创建 Series或 DataFrame 等对象时,索引都会被转换为 Index 对象。
Index | 说明 |
Index | 一般的Index对象 |
MultiIndex | 层次化Index对象 |
DatatimeIndex | Timestamp 索引对象 |
PeriodIndex | Period索引对象 |
Index 对象可以通过 pandas.Index()函数创建,也可以通过创建数据类型对象 Series、 DataFrame 时接收index(或 column)参数创建,前者属于显示创建,后者属于隐式创建。隐式创建中,通过访问 index (或针对 DataFrame 的 column)属性即得到Index。创建的Index 对象不可修改,保证了 Index 对象在各个数据结构之间的安全共享。Series 的索引是一个 Index 对象。
import pandas as pd
list1 = [1, 2, 3, 4, 5]
series = pd.Series(list1, index=['a', 'b', 'c', 'd', 'e'], name='list')
print('通过 dict 创建的 Series 为:\n', series)
print('series 的 Index 为:\n', series.index)
print("series 中 Index 各元素是否大于前一个:", series.index.is_monotonic)
print("series 中 Index 各元素唯一:", series.index.is_unique)
运行结果:
通过 dict 创建的 Series 为:
a 1
b 2
c 3
d 4
e 5
Name: list, dtype: int64
series 的 Index 为:
Index(['a', 'b', 'c', 'd', 'e'], dtype='object')
series 中 Index 各元素是否大于前一个: True
series 中 Index 各元素唯一: True
方法 | 说明 |
difference | 计算两个 Index对象的交集,得到一个新的 Index |
intersection |
计算两个 Index 对象的交集 |
union | 计算两个 Index 对象的并集 |
isin | 计算一个 Index 是否在另一个 Index中,返回bool 数组 |
delete | 删除指定 Index 的元素,并得到新的 Index |
drop | 删除传入的值,并得到新的 Index |
insert | 将元素插入指定Index处,并得到新的 Index |
append | 连接另一个Index 对象,产生一个新的 Index |
unique | 计算 Index 中唯一值的数组 |
import pandas as pd
list1 = [1, 2, 3, 4, 5]
series = pd.Series(list1, index=['a', 'b', 'c', 'd', 'e'], name='list')
list1 = [3, 5, 6, 7, 8]
series1 = pd.Series(list1, index=['d', 'e', 'f', 'g', 'h'], name='list')
print('通过 dict 创建的 Series 为:\n', series)
print('通过 dict 创建的 Series 为:\n', series1)
index1 = series.index
index2 = series1.index
print('index1 连接 index2 后结果为:', index1.append(index2))
print('index1 与 index2 的差集为:', index1.difference(index2))
print('index1 与 index2 的交集为:', index1.intersection(index2))
print('index1 与 index2 的并集为:', index1.union(index2))
print('index1 中的元素是否在 index2 中:', index1.union(index2))
运算结果:
通过 dict 创建的 Series 为:
a 1
b 2
c 3
d 4
e 5
Name: list, dtype: int64
通过 dict 创建的 Series 为:
d 3
e 5
f 6
g 7
h 8
Name: list, dtype: int64
index1 连接 index2 后结果为: Index(['a', 'b', 'c', 'd', 'e', 'd', 'e', 'f', 'g', 'h'], dtype='object')
index1 与 index2 的差集为: Index(['a', 'b', 'c'], dtype='object')
index1 与 index2 的交集为: Index(['d', 'e'], dtype='object')
index1 与 index2 的并集为: Index(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'], dtype='object')
index1 中的元素是否在 index2 中: Index(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'], dtype='object')
通过索引可以实现 DataFrame 内部数据的定向访问、定向提取,以及内容修改。主流的 DataFrame 包括三个方面:基础索引方式、loc 方法和iloc 方法、层次化索引。
import pandas as pd
df = pd.DataFrame({'col1': [0, 1, 2, 3, 4], 'col2': [5, 6, 7, 8, 9]}, index=['a', 'b', 'c', 'd', 'e'])
print('创建的 DataFrame 为:\n', df)
# 访问单列数据
print("DataFrame 中col1 列数据为:\n", df['col1'])
# 以属性的方式访问单列数据
print('DataFrame 中 col2 列数据为:\n', df.col2)
# 访问单列多行数据
print("DataFrame 中 col1 列前 3 行数据为:\n", df['col1'][0:3])
# 访问多列多行数据
print("DataFrame 中 col1 列、col2列前 3 行数据为:\n", df[['col1', 'col2'][0:3]])
# 访问多行数据
print("DataFrame 前 3 行数据为:\n", df[:][0:3])
运行结果:
创建的 DataFrame 为:
col1 col2
a 0 5
b 1 6
c 2 7
d 3 8
e 4 9
DataFrame 中col1 列数据为:
a 0
b 1
c 2
d 3
e 4
Name: col1, dtype: int64
DataFrame 中 col2 列数据为:
a 5
b 6
c 7
d 8
e 9
Name: col2, dtype: int64
DataFrame 中 col1 列前 3 行数据为:
a 0
b 1
c 2
Name: col1, dtype: int64
DataFrame 中 col1 列、col2列前 3 行数据为:
col1 col2
a 0 5
b 1 6
c 2 7
d 3 8
e 4 9
DataFrame 前 3 行数据为:
col1 col2
a 0 5
b 1 6
c 2 7
loc 方法是基于索引名称,iloc 方法基于索引位置
loc 方法
loc 方法是基于名称的索引方法,它接收索引名称(标签),若索引名不存在则会报错。 loc 方法也能够接收整数,但这个整数必须是已存在的索引名称。loc 方法的基本语法格式如下;
DataFrame.loc[行索引名称或条件, 列索引名称]
loc 方法可以像基础索引方式一样访问数据子集。行索引在前,列索引在后,整行或整列用 “:” 代替,当只查看行数据时 “:” 可以省略。
import pandas as pd
df = pd.DataFrame({'col1': [0, 1, 2, 3, 4], 'col2': [5, 6, 7, 8, 9]}, index=['a', 'b', 'c', 'd', 'e'])
print('创建的 DataFrame 为:\n', df)
# 访问单列数据
print("DataFrame 中col1 列数据为:\n", df.loc[:, 'col1'])
# 访问多列数据
print("DataFrame 中 col1 列、col2列数据为:\n", df.loc[:, ['col1', 'col2']])
# 访问单行数据
print("DataFrame 中 a 行数据为:\n", df.loc['a', :])
# 访问多行数据
print("DataFrame 中 a 、c 行数据为:\n", df.loc[['a', 'c'], :])
# 行列结合访问数据
print("DataFrame 中 a 、c 行,col1列、col2列数据为:\n", df.loc[['a', 'c'], ['col1', 'col2']])
# 标签索引切片访问数据
print("DataFrame 中 a ~d 行,col1列、col2列数据为:\n", df.loc['a': 'd', ['col1', 'col2']])
运行结果:
创建的 DataFrame 为:
col1 col2
a 0 5
b 1 6
c 2 7
d 3 8
e 4 9
DataFrame 中col1 列数据为:
a 0
b 1
c 2
d 3
e 4
Name: col1, dtype: int64
DataFrame 中 col1 列、col2列数据为:
col1 col2
a 0 5
b 1 6
c 2 7
d 3 8
e 4 9
DataFrame 中 a 行数据为:
col1 0
col2 5
Name: a, dtype: int64
DataFrame 中 a 、c 行数据为:
col1 col2
a 0 5
c 2 7
DataFrame 中 a 、c 行,col1列、col2列数据为:
col1 col2
a 0 5
c 2 7
DataFrame 中 a ~d 行,col1列、col2列数据为:
col1 col2
a 0 5
b 1 6
c 2 7
d 3 8
loc 方法接收多种输入形式,输入形式包括单个索引名称、索引名称组成的 list,名称切片、bool 类型的数据(Series、list或array)、包含一个参数的函数这 5 种。
使用 loc 方法允许的输入形式进行索引操作
import pandas as pd
df = pd.DataFrame({'col1': [0, 1, 2, 3, 4], 'col2': [5, 6, 7, 8, 9]}, index=['a', 'b', 'c', 'd', 'e'])
print('创建的 DataFrame 为:\n', df)
# 接收 bool 数据
print("DataFrame 中 col1列大于 2 的数据:\n", df.loc[df['col1'] > 2, :])
# 接收函数
print('DataFrame 中 col1列大于 1 的数据:\n', df.loc[lambda df: df['col1'] > 1, :])
运行结果:
创建的 DataFrame 为:
col1 col2
a 0 5
b 1 6
c 2 7
d 3 8
e 4 9
DataFrame 中 col1列大于 2 的数据:
col1 col2
d 3 8
e 4 9
DataFrame 中 col1列大于 1 的数据:
col1 col2
c 2 7
d 3 8
e 4 9
iloc 方法
另一种常用的索引方法是 iloc 。与 loc 方法基于索引不同, iloc 方法完全基于位置,它接收 int ,不能接收索引名称,否则会报错。iloc 的用法与 Numpy 中的 ndarray 的数字索引方式完全相同。iloc 方法的基本语法格式如下
DataFrame.iloc[行索引位置,列索引位置]
使用 iloc 方法访问 DataFrame 的数据子集,基本用法与 loc 类似,行在前,列在后。它们的主要区别如下:
1)loc 方法传入的是索引名称,而 iloc 方法限定 为索引位置
2)loc 方法传入的行索引名称如果为一个区间,那么前后均为闭区间,而 iloc 方法为前闭后开区间。
import pandas as pd
df = pd.DataFrame({'col1': [0, 1, 2, 3, 4], 'col2': [5, 6, 7, 8, 9]}, index=['a', 'b', 'c', 'd', 'e'])
print('创建的 DataFrame 为:\n', df)
# 访问单列数据
print('DataFrame 中 col1 列数据为:\n', df.iloc[:, 0])
# 访问多列数据
print('DataFrame 中 col1 、 col2 列数据为:\n', df.iloc[:, [0, 1]])
# 访问单行数据
print('DataFrame 中 a 行数据为:\n', df.iloc[0, :])
# 访问多行数据
print('DataFrame 中 a 、b行数据为:\n', df.iloc[[0, 1], :])
# 行列结合访问数据
print('DataFrame 中 a、b 行,col1 、 col2 列数据为:\n', df.iloc[[0, 1], [0, 1]])
运行结果:
创建的 DataFrame 为:
col1 col2
a 0 5
b 1 6
c 2 7
d 3 8
e 4 9
DataFrame 中 col1 列数据为:
a 0
b 1
c 2
d 3
e 4
Name: col1, dtype: int64
DataFrame 中 col1 、 col2 列数据为:
col1 col2
a 0 5
b 1 6
c 2 7
d 3 8
e 4 9
DataFrame 中 a 行数据为:
col1 0
col2 5
Name: a, dtype: int64
DataFrame 中 a 、b行数据为:
col1 col2
a 0 5
b 1 6
DataFrame 中 a、b 行,col1 、 col2 列数据为:
col1 col2
a 0 5
b 1 6
使用 append() 函数,可以将新的数据行添加到 DataFrame 中,该函数会在行末尾追加数据行。
df.append(other, ignore_index=False, verify_integrity=False,sort=False)
将 “other” 追加到调用者的末尾,返回一个新对象。 “other”行中不在调用者中的列将作为新列添加。
import pandas as pd
data = {
'Name': ['关羽', '刘备', '张飞', '曹操'],
'Age': [28, 34, 29, 42],
"Salary": [5000, 8000, 4500, 10000]
}
df = pd.DataFrame(data)
print(f"原始 DataFrame 为:\n{df}")
# Series 数据有 name
d2 = {'Name': '诸葛亮', 'Age': 30}
# 在行末尾追加新数据行
df3 = df.append(d2, ignore_index=True) # 设置为True,否则报错
print(f"添加一行数据后 DataFrame df3 为:\n{df3}")
# 在行末尾追加新数据行
s = pd.Series(d2, name='a')
df4 = df.append(s)
print(f"添加一行数据后 DataFrame df4 为:\n{df4}")
运行结果:
原始 DataFrame 为:
Name Age Salary
0 关羽 28 5000
1 刘备 34 8000
2 张飞 29 4500
3 曹操 42 10000
添加一行数据后 DataFrame df3 为:
Name Age Salary
0 关羽 28 5000.0
1 刘备 34 8000.0
2 张飞 29 4500.0
3 曹操 42 10000.0
4 诸葛亮 30 NaN
添加一行数据后 DataFrame df4 为:
Name Age Salary
0 关羽 28 5000.0
1 刘备 34 8000.0
2 张飞 29 4500.0
3 曹操 42 10000.0
a 诸葛亮 30 NaN
追加列表
注意:使用 append 可能会出现相同的 index ,想避免的话,可以使用 ignore_index=True
您可以使用行索引标签,从 DataFrame 中删除某一行数据。如果索引标签存在重复,那么它们将被以其删除。
import pandas as pd
df = pd.DataFrame([[1, 2], [3, 4]], columns=['a', 'b'])
df2 = pd.DataFrame([[5, 6], [7, 8]], columns=['a', 'b'])
df = df.append(df2)
print(f'原始数据:\n{df}')
# 注意此处调用了 drop() 方法,注意 drop 默认不会更改源数据
df1 = df.drop(0)
print(f'修改后的数据为:\n{df1}')
运行结果:
原始数据:
a b
0 1 2
1 3 4
0 5 6
1 7 8
修改后的数据为:
a b
1 3 4
1 7 8
单层索引能够应付一般的数据处理工作,但在特殊场景中,层次化索引能够更加便捷。pandas 提供了 MultiIndex 对象,能够在一个轴上拥有两个以上的索引。
类似 Index 对象,创建层次化索引的方式也分为显示创建和隐式创建。显示创建即采用独立的官方语法,如 pandas.MultiIndex.from_tuples 等创建。隐式创建即通过创建数据对象,如 Series、DataFrame 时接收 index(或 column)参数创建,此时参数须为嵌套的数组或 list。创建一个拥有多索引的 DataFrame, 此时的索引为 MultiIndex 对象,访问 DataFrame 的索引,代码如下:
import pandas as pd
import numpy as np
multiindex = [['bar', 'bar', 'baz', 'baz', 'foo', 'foo', 'qux', 'qux'],
['one', 'two', 'one', 'two', 'one', 'two', 'one', 'two']]
df1 = pd.DataFrame(np.arange(16).reshape(8, 2), index=multiindex,
columns=['column1', 'column2'])
print('创建的 DataFrame 为:\n', df1)
print(' DataFrame 的层次化索引为:\n', df1.index)
print('访问 DataFrame 的第 1 索引层 bar ,第 2 索引层 two 的结果为:\n', df1.loc[('bar', 'two'), :])
print('访问 DataFrame 的第 1 索引层 bar 、baz、foo,第 2 索引层 one, two 的结果为:\n', df1.loc[(['bar', 'baz', 'foo'], ['one', 'two']), :])
运行结果:
创建的 DataFrame 为:
column1 column2
bar one 0 1
two 2 3
baz one 4 5
two 6 7
foo one 8 9
two 10 11
qux one 12 13
two 14 15
DataFrame 的层次化索引为:
MultiIndex([('bar', 'one'),
('bar', 'two'),
('baz', 'one'),
('baz', 'two'),
('foo', 'one'),
('foo', 'two'),
('qux', 'one'),
('qux', 'two')],
)
访问 DataFrame 的第 1 索引层 bar ,第 2 索引层 two 的结果为:
column1 2
column2 3
Name: (bar, two), dtype: int32
访问 DataFrame 的第 1 索引层 bar 、baz、foo,第 2 索引层 one, two 的结果为:
column1 column2
bar one 0 1
two 2 3
baz one 4 5
two 6 7
foo one 8 9
two 10 11
无法对索引层进行切片操作,使用“:” 会报错 pandas 提供 slice 方法,用于对索引层进行操作,slice(None) 表示选中全部
import pandas as pd
import numpy as np
multiindex = [['bar', 'bar', 'baz', 'baz', 'foo', 'foo', 'qux', 'qux'],
['one', 'two', 'one', 'two', 'one', 'two', 'one', 'two']]
df1 = pd.DataFrame(np.arange(16).reshape(8, 2), index=multiindex,
columns=['column1', 'column2'])
print('创建的 DataFrame 为:\n', df1)
print('访问 DataFrame 的第 1 索引层 bar 、baz、foo,第 2 索引层 one, two 的结果为:\n', df1.loc[(slice('bar', 'foo'), slice(None)), :])
运行结果:
创建的 DataFrame 为:
column1 column2
bar one 0 1
two 2 3
baz one 4 5
two 6 7
foo one 8 9
two 10 11
qux one 12 13
two 14 15
访问 DataFrame 的第 1 索引层 bar 、baz、foo,第 2 索引层 one, two 的结果为:
column1 column2
bar one 0 1
two 2 3
baz one 4 5
two 6 7
foo one 8 9
two 10 11
想要更自然的进行索引层切片操作,pandas 官方推荐使用 pandas.IndexSlice 方法,将它与loc 方法结合起来使用更加自然。 pandas.IndexSlice 方法可以对每个索引层分别操作,用逗号隔开即可。它可以接收单个标签、标签 list和标签切片,甚至可以接收 bool 数组用于条件筛选。 pandas.IndexSlice 方法让更多索引操作变得和但索引操作一样简单,代码操作如下:
import pandas as pd
import numpy as np
multiindex = [['bar', 'bar', 'baz', 'baz', 'foo', 'foo', 'qux', 'qux'],
['one', 'two', 'one', 'two', 'one', 'two', 'one', 'two']]
df1 = pd.DataFrame(np.arange(16).reshape(8, 2), index=multiindex,
columns=['column1', 'column2'])
print('创建的 DataFrame 为:\n', df1)
# 接收单个标签
idx = pd.IndexSlice
print('访问 DataFrame 第1 索引层 bar,第 2 索引层 two 的结果为:\n', df1.loc[idx['bar', 'two'], :])
# 接收标签list
print('访问 DataFrame 的第 1 索引层 bar 、foo,第 2 索引层 two 的结果为:\n', df1.loc[idx[['bar', 'foo'], 'two'], :])
# 接收标签切片
print('访问 DataFrame 的第 1 索引层 bar 到foo,第 2 索引层 two 的结果为:\n', df1.loc[idx['bar': 'foo', 'two'], :])
# 接收 bool 数组
con = df1['column1'] > 0
print('访问 DataFrame 的第 1 索引层 bar 到foo,第 2 索引层对应的 column1 列大于0的结果为:\n',
df1.loc[idx['bar': 'foo', con], :])
运行结果:
创建的 DataFrame 为:
column1 column2
bar one 0 1
two 2 3
baz one 4 5
two 6 7
foo one 8 9
two 10 11
qux one 12 13
two 14 15
访问 DataFrame 第1 索引层 bar,第 2 索引层 two 的结果为:
column1 2
column2 3
Name: (bar, two), dtype: int32
访问 DataFrame 的第 1 索引层 bar 、foo,第 2 索引层 two 的结果为:
column1 column2
bar two 2 3
foo two 10 11
访问 DataFrame 的第 1 索引层 bar 到foo,第 2 索引层 two 的结果为:
column1 column2
bar two 2 3
baz two 6 7
foo two 10 11
访问 DataFrame 的第 1 索引层 bar 到foo,第 2 索引层对应的 column1 列大于0的结果为:
column1 column2
bar two 2 3
baz one 4 5
two 6 7
foo one 8 9
two 10 11
排序包含索引排序和按值排序
sort_index 方法用于对 DataFrame 按索引排序,其基本语法格式如下
DataFrame.sort_index(axis = 0, level = None, ascending = True, inplace = False)
参数名称 | 说明 |
axis | 接收0或1,表示排序作用的轴,0为行排序。默认为0。 |
level | 接收int、list或string,表示索引级别。默认为None |
ascending | 接收bool ,表示排序方式,False表示升序。默认为False |
inplace | 接收 bool ,表示操作是否对原数据生效。默认为False |
import pandas as pd
df = pd.DataFrame({'col1': [0, 1, 2, 3, 4], 'col2': [5, 6, 7, 8, 9]}, index=['a', 'b', 'c', 'd', 'e'])
print('创建的 DataFrame 为:\n', df)
# 按行索引排序
print('按行索引排序后的 DataFrame 为:\n', df.sort_index(axis=0))
# 按列索引升序排列
print('按列索引排序后的 DataFrame 为:\n', df.sort_index(axis=1, ascending=False))
运行结果:
创建的 DataFrame 为:
col1 col2
a 0 5
b 1 6
c 2 7
d 3 8
e 4 9
按行索引排序后的 DataFrame 为:
col1 col2
a 0 5
b 1 6
c 2 7
d 3 8
e 4 9
按列索引排序后的 DataFrame 为:
col2 col1
a 5 0
b 6 1
c 7 2
d 8 3
e 9 4
sort_values 方法用于按值排序。
DataFrame.sort_values(by, axis = 0, ascending = True, inplace = False)
参数名称 | 说明 |
by | 接收str或由 str 组成的 list,表示排序依据的值,可以为列名或索引名。无默认值 |
axis | 接收0或1,表示排序作用的轴,0为行排序。默认为0。 |
ascending | 接收bool ,表示排序方式,False表示升序。默认为False |
inplace | 接收 bool ,表示操作是否对原数据生效。默认为False |
import pandas as pd
df = pd.DataFrame({'col1': [0, 1, 2, 3, 4], 'col2': [5, 6, 7, 8, 9]}, index=['a', 'b', 'c', 'd', 'e'])
print('创建的 DataFrame 为:\n', df)
# 按列排序
print('按col2 列排序后的 DataFrame 为:\n', df.sort_values('col2'))
# 按行降序排列
print('按列索引排序后的 DataFrame 为:\n', df.sort_values('a', axis=1, ascending=False))
# 使用nlargest 方法和 nsmallest 方法按列排序
print('按 col2 列排序, 返回前 2 个最小值为:\n', df.nsmallest(2, 'col2'))
print('按 col2 列排序, 返回前 2 个最大值为:\n', df.nlargest(2, 'col2'))
运行结果:
创建的 DataFrame 为:
col1 col2
a 0 5
b 1 6
c 2 7
d 3 8
e 4 9
按col2 列排序后的 DataFrame 为:
col1 col2
a 0 5
b 1 6
c 2 7
d 3 8
e 4 9
按列索引排序后的 DataFrame 为:
col2 col1
a 5 0
b 6 1
c 7 2
d 8 3
e 9 4
按 col2 列排序, 返回前 2 个最小值为:
col1 col2
a 0 5
b 1 6
按 col2 列排序, 返回前 2 个最大值为:
col1 col2
e 4 9
d 3 8
将不同的 DataFrame 通过不同的手段变为一个,这个过程叫数据合并。常见的数据合并操作主要有两种:堆叠合并和主键合并。
堆叠就是把两个表拼在一起,也被称为轴向连接。依据连接轴的方向,数据堆叠可分为横向堆叠和纵向堆叠。 pandas 提供concat 函数,用于表堆叠,其基本语法格式:
pandas.concat(objs, axis = 0, join='outer, join_axes=None, ignore_index=False,
keys=None, levels=None, verify_integrity=False, copy=True)
参数名称 | 说明 |
objs | 接收多个 Series、DataFrame、Panels的组合,表示参与连接的pandas对象的 list 的组合 |
axis | 接收0或1,表示连接的轴向,0表示横向堆叠,1表示纵向堆叠。默认0 |
join | 接收特定 str("inner" ”outer“),表示其他轴向上的索引是按交集(inner)还是按照并(outer)集进行合并。默认为outer |
join_axes | 接收索引对象,表示用于其他 n-1 条的索引,不执行并集/交集运算 |
ignore_index | 接收 bool ,表示是否不保留连接轴上的索引,产生一组新 Indexrange(total_length)。默认为None |
keys | 接收 sequence,表示与连接对象有关的值,用于形成连接轴向上的层次化索引。默认为None |
levels | 接收包含多个 sequence 的 list,表示在指定 keys 参数后,指定用作层次化索引各级别上的索引。默认为None |
names | 接收 list ,表示在设置了 keys 和 levels 参数后,用于传播创建分级别的名称。默认为None |
verify_integrity | 接收 boolean,表示是否检查结果对象新轴上的重复情况,如果发现则引发异常。 |
(1)横向堆叠
横向堆叠,即将两个表在 X 轴向拼接在一起, concat 函数能实现横向堆叠。当 axis = 1 的时候, concat 函数做行对齐,然后将不同列名称的两张或多张表合并,从而实现横向堆叠。当两个表的索引不完全一样时,可以使用 join 参数选择是内连接还是外连接,默认为外连接。在内连接的情况下,仅仅返回索引的重叠部分;在外连接的情况下,则显示并集部分数据,不足的地方则使用空值填补。
import pandas as pd
df2 = pd.DataFrame({'key': ['k0', 'k1', 'k2', 'k3', 'k4', 'k5'], 'A': ['A0', 'A1', 'A2', 'A3', 'A4', 'A5']})
df3 = pd.DataFrame({'key': ['k0', 'k1', 'k2'], 'A': ['B0', 'B1', 'B2']})
print('创建的 DataFrame df2为:\n', df2)
print('创建的 DataFrame df3为:\n', df3)
# 横向堆叠 df2、df3
print("横向堆叠 df2、df3 的DataFrame 为:\n", pd.concat([df2, df3], axis=1))
# 横向堆叠(内连) df2、df3
print("横向堆叠(内连) df2、df3 的DataFrame 为:\n", pd.concat([df2, df3], axis=1, join='inner'))
运行结果:
创建的 DataFrame df2为:
key A
0 k0 A0
1 k1 A1
2 k2 A2
3 k3 A3
4 k4 A4
5 k5 A5
创建的 DataFrame df3为:
key A
0 k0 B0
1 k1 B1
2 k2 B2
横向堆叠 df2、df3 的DataFrame 为:
key A key A
0 k0 A0 k0 B0
1 k1 A1 k1 B1
2 k2 A2 k2 B2
3 k3 A3 NaN NaN
4 k4 A4 NaN NaN
5 k5 A5 NaN NaN
横向堆叠(内连) df2、df3 的DataFrame 为:
key A key A
0 k0 A0 k0 B0
1 k1 A1 k1 B1
2 k2 A2 k2 B2
除了 concat 函数 ,join 方法也可以用于简单的横向堆叠。基本语法格式如下:
pandas.DataFrame.join(self, other, on=None, how='left', lsuffix='',rsuffix='',sort=False)
参数名称 | 说明 |
other | 接收 DataFrame、Series 或者包含了多个 DataFrame 的 list,表示参与连接的其他 DataFrame 。无默认值 |
on | 接收列名或者包含列名的 list 或 tuple,表示用于连接的列名。默认为None |
how | 接收特定 string ,inner 代表内连接; outer代表外连接; left 和 right 分别代表左连接和右连接 |
lsuffix | 接收 string,表示用于追加到左侧重叠列名的末尾。无默认 |
rsuffix | 接收 string,表示用于追加到右侧重叠列名的末尾。无默认 |
sort | 根据连接键对合并后的数据进行排序。默认为True |
当横向堆叠的两个表的列名有相同时,需设置 lsuffix 或 rsuffix 参数以示区别,否则会报错
import pandas as pd
df2 = pd.DataFrame({'key': ['k0', 'k1', 'k2', 'k3', 'k4', 'k5'], 'A': ['A0', 'A1', 'A2', 'A3', 'A4', 'A5']})
df3 = pd.DataFrame({'key': ['k0', 'k1', 'k2'], 'A': ['B0', 'B1', 'B2']})
print('创建的 DataFrame df2为:\n', df2)
print('创建的 DataFrame df3为:\n', df3)
# 横向堆叠 df2、df3
print("横向堆叠 df2、df3 的DataFrame 为:\n",df2.join(df3,rsuffix='_2'))
运行结果:
创建的 DataFrame df2为:
key A
0 k0 A0
1 k1 A1
2 k2 A2
3 k3 A3
4 k4 A4
5 k5 A5
创建的 DataFrame df3为:
key A
0 k0 B0
1 k1 B1
2 k2 B2
横向堆叠 df2、df3 的DataFrame 为:
key A key_2 A_2
0 k0 A0 k0 B0
1 k1 A1 k1 B1
2 k2 A2 k2 B2
3 k3 A3 NaN NaN
4 k4 A4 NaN NaN
5 k5 A5 NaN NaN
(2)纵向堆叠
与横向堆叠不同,纵向堆叠是将两个数据表在 Y 轴向上拼接,concat 函数可以实现纵向堆叠。使用 concat 函数时,在默认情况下,即 axis=0,concat 做列对齐,将不同行索引的两张或多张表纵向合并,从而实现纵向堆叠。在两张表的列名并不完全相同的情况下,join参数取值为 inner 时,返回的仅仅是列名交集所代表的列;取值为 outer 时,它是默认值,返回的是两者列名的并集所代表的列。
import pandas as pd
df2 = pd.DataFrame({'key': ['k0', 'k1', 'k2', 'k3', 'k4', 'k5'], 'A': ['A0', 'A1', 'A2', 'A3', 'A4', 'A5']})
df3 = pd.DataFrame({'key': ['k0', 'k1', 'k2'], 'B': ['B0', 'B1', 'B2']})
print('创建的 DataFrame df2为:\n', df2)
print('创建的 DataFrame df3为:\n', df3)
# 纵向堆叠 df2、df3
print("纵向堆叠 df2、df3 的DataFrame 为:\n", pd.concat([df2, df3], axis=0))
# 纵向堆叠(内连) df2、df3
print("纵向堆叠(内连) df2、df3 的DataFrame 为:\n", pd.concat([df2, df3], axis=0, join='inner'))
运行结果:
创建的 DataFrame df2为:
key A
0 k0 A0
1 k1 A1
2 k2 A2
3 k3 A3
4 k4 A4
5 k5 A5
创建的 DataFrame df3为:
key B
0 k0 B0
1 k1 B1
2 k2 B2
纵向堆叠 df2、df3 的DataFrame 为:
key A B
0 k0 A0 NaN
1 k1 A1 NaN
2 k2 A2 NaN
3 k3 A3 NaN
4 k4 A4 NaN
5 k5 A5 NaN
0 k0 NaN B0
1 k1 NaN B1
2 k2 NaN B2
纵向堆叠(内连) df2、df3 的DataFrame 为:
key
0 k0
1 k1
2 k2
3 k3
4 k4
5 k5
0 k0
1 k1
2 k2
除了concat 函数 ,append 方法也可用于简单的纵向堆叠,这对列名完全相同的两张表特别有用,列名不同则会被空值替代。基本语法如下:
pandas.DataFrame.append(self,other,ignore_index=False,verify_integrity=False)
参数名称 | 说明 |
other | 接收 DataFrame或Series,表示要添加的新数据。无默认值 |
ignore_index | 接收 boolean,如果输入True ,会对新生成的 DataFrame 使用新的索引(自动产生)而忽略原来数据的索引。默认为False |
verify_integrity | 接收 boolean,如果输入 True,那么当 ignore_index 为 False 时,会检查添加的数据索引是否冲突,则会添加失败。默认为False |
import pandas as pd
df2 = pd.DataFrame({'key': ['k0', 'k1', 'k2', 'k3', 'k4', 'k5'], 'A': ['A0', 'A1', 'A2', 'A3', 'A4', 'A5']})
df3 = pd.DataFrame({'key': ['k0', 'k1', 'k2'], 'B': ['B0', 'B1', 'B2']})
print('创建的 DataFrame df2为:\n', df2)
print('创建的 DataFrame df3为:\n', df3)
# 纵向堆叠 df2、df3
print("纵向堆叠 df2、df3 的DataFrame 为:\n", df2.append(df3))
运行结果:
创建的 DataFrame df2为:
key A
0 k0 A0
1 k1 A1
2 k2 A2
3 k3 A3
4 k4 A4
5 k5 A5
创建的 DataFrame df3为:
key B
0 k0 B0
1 k1 B1
2 k2 B2
纵向堆叠 df2、df3 的DataFrame 为:
key A B
0 k0 A0 NaN
1 k1 A1 NaN
2 k2 A2 NaN
3 k3 A3 NaN
4 k4 A4 NaN
5 k5 A5 NaN
0 k0 NaN B0
1 k1 NaN B1
2 k2 NaN B2
不牵扯时区的问题,便于计算
时间格式转换图
# 导入 time 模块
import time
# 生成 timestamp
# print(int(time.time()))
# 程序开发时间
start_time = time.time()
# 程序
s =""
for i in range(10000):
s += str(i)
# sleep(睡眠多少秒)
# time.sleep(1) # 程序暂停 1 秒
end_time = time.time()
print(f'程序消耗时间={end_time-start_time}')
运行结果:
程序消耗时间=0.002516508102416992
# 导入 time 模块
import time
# 生成struct_time
# timestamp to struct_time 本地时间
my_time = time.localtime()
print(f'my_time 为:{my_time}')
print(my_time.tm_year)
print(my_time.tm_mon)
print(my_time.tm_mday)
# 将timesstamp 转化为 struct_time
print(time.localtime(1650177058))
print(f'----------分割线-----------')
print(time.strftime('%Y-%m-%d')) # 默认当前时间格式化
# 显示指定 struct_time 格式化后的时间
print(time.strftime('%Y-%m-%d', time.localtime(1650177058)))
print(time.strftime('%Y-%m-%d %X', time.localtime(1650177058)))
# 将格式化字符串到 struct_time,再转为时间戳
st = time.strptime('2011-05-05 16:37:06', '%Y-%m-%d %X')
print(time.mktime(st))
# 时间戳加 10 天
print(time.mktime(st) + 24*60*60*10)
运行结果:
my_time 为:time.struct_time(tm_year=2022, tm_mon=11, tm_mday=11, tm_hour=22, tm_min=6, tm_sec=2, tm_wday=4, tm_yday=315, tm_isdst=0)
2022
11
11
time.struct_time(tm_year=2022, tm_mon=4, tm_mday=17, tm_hour=14, tm_min=30, tm_sec=58, tm_wday=6, tm_yday=107, tm_isdst=0)
----------分割线-----------
2022-11-11
2022-04-17
2022-04-17 14:30:58
1304584626.0
1305448626.0
datetime 模块重新封装了 time 模块,提供更多接口,提供的类有:date, time, datetime, timedelta, tzinfo
1. date 类
datetime.date(year, month, day)
静态方法和字段
from datetime import date
# 导入 time 模块
import time
print(f'date.today():{date.today()}')
print(f'date.fromtimestamp():{date.fromtimestamp(time.time())}')
运行结果:
date.today():2022-11-12
date.fromtimestamp():2022-11-12
from datetime import date
# 导入 time 模块
import time
now = date(2021, 10, 26)
print(now.year, now.month, now.day)
tomorrow = now.replace(day=1)
print(f'now:{now},当月第一天:{tomorrow}')
print(f'timetuple(): {now.timetuple()}')
print(f'weekday(): {now.weekday()}')
print(f'isoweekday(): {now.isoweekday()}')
print(f'isoformat(): {now.isoformat()}')
print(f'strftime(): {now.strftime("%Y.%m.%d")}')
运行结果:
2021 10 26
now:2021-10-26,当月第一天:2021-10-01
timetuple(): time.struct_time(tm_year=2021, tm_mon=10, tm_mday=26, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=1, tm_yday=299, tm_isdst=-1)
weekday(): 1
isoweekday(): 2
isoformat(): 2021-10-26
strftime(): 2021.10.26
2. datetime 类
datetime 相当于 date 和 time 结合起来
部分常用属性和方法:
// 通过datetime对象才能调用
dt.year、dt.month、dt.day:获取年、月、日;
dt.hour、dt.minute、dt.second、dt.microsecond:获取时、分、秒、微秒;
datetime.fromtimestamp():将时间戳转为一个datetime对象
dt.date():获取date对象;
dt.time():获取time对象;
dt.replace():传入指定的year或month或day或hour或minute或second或microsecond,生成一个新日期datetime对象,但不改变原有的datetime对象;
dt.timetuple():返回时间元组struct_time格式的日期;
dt.weekday():返回weekday,如果是星期一,返回0;如果是星期2,返回1,以此类推;
dt.isoweekday():返回weekday,如果是星期一,返回1;如果是星期2,返回2,以此类推;
dt.isocalendar():返回(year,week,weekday)格式的元组;
dt.isoformat():返回固定格式如'YYYY-MM-DD HH:MM:SS’的字符串
dt.strftime(format):传入任意格式符,可以输出任意格式的日期表示形式。
from datetime import datetime
# 导入 time 模块
import time
now = datetime.now()
print(type(now))
# 将datetime 转化为指定格式的字符串
print(now.strftime('%Y-%m-%d %X'))
print(now.strftime('%Y-%m-%d %H:%M'))
# '2021-11-10 10:23',使用strptime 将字符串转 datetime(格式要统一)
my_str = '2021-11-10 10:23'
print(datetime.strptime(my_str, '%Y-%m-%d %H:%M'))
print(f'获取date对象:{now.date()}')
print(f'获取time对象:{now.time()}')
print(f'返回时间元组struct_time格式的日期:{now.timetuple()}')
运行结果:
2022-11-12 16:43:13
2022-11-12 16:43
2021-11-10 10:23:00
获取date对象:2022-11-12
获取time对象:16:43:13.423626
返回时间元组struct_time格式的日期:time.struct_time(tm_year=2022, tm_mon=11, tm_mday=12, tm_hour=16, tm_min=43, tm_sec=13, tm_wday=5, tm_yday=316, tm_isdst=-1)
使用 timedelta 可以很方便的在日期上做天 days,小时 hour,分钟,秒,毫秒,微妙的时间计算,如果要计算月份则需要另外的办法
from datetime import datetime
from datetime import timedelta
dt = datetime.now()
# 日期减一天
dt_1 = dt + timedelta(days=-1) # 昨天
dt_2 = dt - timedelta(days=1) # 昨天
dt_3 = dt + timedelta(days=1) # 明天
print(f'今天:{dt}')
print(f'昨天:{dt_1}')
print(f'昨天:{dt_2}')
print(f'明天:{dt_3}')
# 明天的 datetime- 昨天的datetime
s =dt_3 - dt_1
print(f'相差的天数:{s.days}')
print(f'相差的秒数:{s.total_seconds()}')
运行结果:
今天:2022-11-12 17:05:10.986492
昨天:2022-11-11 17:05:10.986492
昨天:2022-11-11 17:05:10.986492
明天:2022-11-13 17:05:10.986492
相差的天数:2
相差的秒数:172800.0
表示持续时间,即两个日期或时间之间的差异。
相当于 python 的datetime.timedelta ,在大多数情况下可以与之互换
import time
import pandas as pd
from datetime import datetime
from datetime import timedelta
ts = pd.Timestamp('2022-11-12 12')
print(ts)
# 减一天
print(f'减去一天后:{ts + pd.Timedelta(-1, "D")}')
# 时间间隔
td = pd.Timedelta(days=5, minutes=50, seconds=20) # 关键字赋值
print(f'ts + td ={ts + td}')
print(f'总秒数:{td.total_seconds()}')
运行结果:
2022-11-12 12:00:00
减去一天后:2022-11-11 12:00:00
ts + td =2022-11-17 12:50:20
总秒数:435020.0
to_datetime 转换时间戳,可以通过 to_datetime 能快速将字符串转换为时间戳。当传递一个 Series 时,它会返回一个 Series(具有相同的索引),而类似列表的则转换为 DatetimeIndex
import pandas as pd
df = pd.DataFrame({'year': [2015, 2016], 'month': [2, 3], 'day': [4, 5]})
print(df)
print(f'pd.Datetime(df):\n{pd.to_datetime(df)}')
# 将字符串转为 datetime
print(pd.to_datetime(['11-12-2021']))
print(pd.to_datetime(['2005/11/13', "2010.12.31"]))
# 除了可以将文本数据转换为时间戳外,还可以将 unix 时间转换为时间戳
print(pd.to_datetime([1349720105, 1349806505, 1349892905], unit="s"))
# 自动识别异常
print(pd.to_datetime('210605'))
print(pd.to_datetime('210605', yearfirst=True))
# 配合 uint 参数,使用非unix 时间
print(pd.to_datetime([1, 2, 3], unit='D', origin=pd.Timestamp('2020-01-11')))
print(pd.to_datetime([1, 2, 3], unit='d'))
print(pd.to_datetime([1, 2, 3], unit='h', origin=pd.Timestamp('2020-01')))
print(pd.to_datetime([1, 2, 3], unit='m', origin=pd.Timestamp('2020-01')))
print(pd.to_datetime([1, 2, 3], unit='s', origin=pd.Timestamp('2020-01')))
运行结果:
year month day
0 2015 2 4
1 2016 3 5
pd.Datetime(df):
0 2015-02-04
1 2016-03-05
dtype: datetime64[ns]
DatetimeIndex(['2021-11-12'], dtype='datetime64[ns]', freq=None)
DatetimeIndex(['2005-11-13', '2010-12-31'], dtype='datetime64[ns]', freq=None)
DatetimeIndex(['2012-10-08 18:15:05', '2012-10-09 18:15:05',
'2012-10-10 18:15:05'],
dtype='datetime64[ns]', freq=None)
2005-06-21 00:00:00
2021-06-05 00:00:00
DatetimeIndex(['2020-01-12', '2020-01-13', '2020-01-14'], dtype='datetime64[ns]', freq=None)
DatetimeIndex(['1970-01-02', '1970-01-03', '1970-01-04'], dtype='datetime64[ns]', freq=None)
DatetimeIndex(['2020-01-01 01:00:00', '2020-01-01 02:00:00',
'2020-01-01 03:00:00'],
dtype='datetime64[ns]', freq=None)
DatetimeIndex(['2020-01-01 00:01:00', '2020-01-01 00:02:00',
'2020-01-01 00:03:00'],
dtype='datetime64[ns]', freq=None)
DatetimeIndex(['2020-01-01 00:00:01', '2020-01-01 00:00:02',
'2020-01-01 00:00:03'],
dtype='datetime64[ns]', freq=None)
有时候,我们可能想要生成某个范围内的时间戳。例如,我想要生成“2018-6-26” 这一天之后的 8 天时间戳,我们可以使用 date_range 和 bdate_range 来完成时间戳范围的生成。
import pandas as pd
# 指定默认值,默认时包含开始和结束时间,默认频率使用的D(天)
print(pd.date_range(start='1/1/2021', end='1/08/2021'))
print(pd.date_range(start='2010', end='2011'))
# 指定开始日期,设置期间数
print(pd.date_range(start='1/1/2018', periods=8))
# 指定开始、结束和期间;频率自动生成(线性间隔)
print(pd.date_range(start='2018-04-24', end='2018-04-27', periods=3))
print(pd.date_range(start='2018-04-24', end='2018-04-27', periods=4))
print(pd.date_range(start='2018-04-24', periods=4))
print(pd.date_range(start='2018-04-24 15:30', periods=4, name='mypd'))
print(pd.date_range(start='2018-04-24 15:30', periods=4, name='mypd', normalize=True))
运行结果:
DatetimeIndex(['2021-01-01', '2021-01-02', '2021-01-03', '2021-01-04',
'2021-01-05', '2021-01-06', '2021-01-07', '2021-01-08'],
dtype='datetime64[ns]', freq='D')
DatetimeIndex(['2010-01-01', '2010-01-02', '2010-01-03', '2010-01-04',
'2010-01-05', '2010-01-06', '2010-01-07', '2010-01-08',
'2010-01-09', '2010-01-10',
...
'2010-12-23', '2010-12-24', '2010-12-25', '2010-12-26',
'2010-12-27', '2010-12-28', '2010-12-29', '2010-12-30',
'2010-12-31', '2011-01-01'],
dtype='datetime64[ns]', length=366, freq='D')
DatetimeIndex(['2018-01-01', '2018-01-02', '2018-01-03', '2018-01-04',
'2018-01-05', '2018-01-06', '2018-01-07', '2018-01-08'],
dtype='datetime64[ns]', freq='D')
DatetimeIndex(['2018-04-24 00:00:00', '2018-04-25 12:00:00',
'2018-04-27 00:00:00'],
dtype='datetime64[ns]', freq=None)
DatetimeIndex(['2018-04-24', '2018-04-25', '2018-04-26', '2018-04-27'], dtype='datetime64[ns]', freq=None)
DatetimeIndex(['2018-04-24', '2018-04-25', '2018-04-26', '2018-04-27'], dtype='datetime64[ns]', freq='D')
DatetimeIndex(['2018-04-24 15:30:00', '2018-04-25 15:30:00',
'2018-04-26 15:30:00', '2018-04-27 15:30:00'],
dtype='datetime64[ns]', name='mypd', freq='D')
DatetimeIndex(['2018-04-24', '2018-04-25', '2018-04-26', '2018-04-27'], dtype='datetime64[ns]', name='mypd', freq='D')