概述:
Pandas 是一个开源的第三方 Python 库,是一个强大的分析结构化数据的工具集,基础是 Numpy(提供高性能的矩阵运算),用于数据分析,广泛应用在学术、金融、统计学等各个数据分析领域。
ps:由于 pandas 库约定成俗会在导入时起别名as,故下述内容中的pandas
安装:
pip install pandas -i https://pypi.tuna.tsinghua.edu.cn/simple/
数据结构:
Pandas库中有两种不同的数据结构,分别是 Series(一维数据结构)、DataFrame(二维数据结构):
-
Series 是带标签的一维数组,这里的标签可以理解为索引,但这个索引并不局限于整数,它也可以是字符类型,比如 a、b、c 等
-
DataFrame 是一种表格型数据结构,它既有行标签,又有列标
Dataframe和Series的关系:
在 Pandas 中,DataFrame 的每一行或每一列都是一个 Series。
DataFrame 是一个二维表格,可以看作是由多个 Series 组成的。
Series:
创建 Series 对象:
serise = pandas.Series(data,index,dtype)
参数: data:一组数据 index:数据索引标签(传入一个数组或列表用以指定索引标签),如果 不指定,默认从 0 开始 dtype:数据类型,默认会自己判断 copy:表示对 data 进行拷贝,默认为 False |
import pandas as pd
# 字典创建 Series 对象
data = {"name": "zhangsan", "gender": "男"} # 字典中的 key 会成为标签,value 会成为值
result = pd.Series(data=data)
print('字典创建 Series 对象:')
print(result)
"""
字典创建 Series 对象:
name zhangsan
gender 男
dtype: object
"""
访问和修改 Serise 对象的数据:
s = pd.Series([10, 20, 30], index=['a', 'b', 'c'])
print(s)
# 根据标签名获取元素
b = s['b']
print(b)
# 根据数组下标获取元素
b1 = s[1]
print(b1)
# 根据标签名修改元素值
s['a'] = 100
print(s)
# 根据下标修改元素值
s[1] = 200
print(s)
遍历Series对象中的元素
s = pd.Series([1, 2, 3, 4, 5])
# 类似python list的方式遍历
for i in s:
print(i, end=' ')
print('------------------')
# items():返回Series对象索引和值
for index, value in s.items():
print(index, value)
# 通过index遍历
for index in s.index:
print(index, s[index])
# 通过values遍历
for v in s.values:
print(v)
DataFrame:
创建 DataFrame 对象:
df = pd.DataFrame( data, index, columns, dtype, copy)
参数: data:一组数据(ndarray、series, map, lists, dict 等类型) index:索引值,或者可以称为行标签 columns:列标签,默认为 RangeIndex (0, 1, 2, …, n) dtype:数据类型 copy:默认为 False,表示复制数据 data |
import pandas as pd
# 列表嵌套字典创建 DataFrame 对象
def four():
data = [{'name': "张三", 'age': 18},{'name': "小红", 'gender': "男", 'age': 19}]
result = pd.DataFrame(data=data)
print(result)
"""
name age gender
0 张三 18 NaN
1 小红 19 男
"""
访问 DataFrame 中的数据:
列操作
列元素的索引与增加
def test01():
df = pd.DataFrame({'name': ['zhangsan', 'lisi'], 'age': [20, 30], 'id': [1, 2]})
# 根据列名获取某一列的数据,结果是列的Series对象
s = df['name']
print(s)
# 将Series转换为python列表
print(list(s))
# 通过布尔索引获取数据
df1 = df[df['age'] > 20]
print(df1)
# 添加一列空数据,在df中要指定新列名:df['sex']
df['sex'] = None
print(df)
# 添加一列数据,数据的格式可以是python列表、Series对象等
df['sex'] = ['男', '女']
print(df)
# assign(key=values):添加新列,key作为Dataframe的列名,value作为DataFrame的列值,可以链式调用
df = df.assign(address=['四川省', '重庆市']).assign(password=['12345', '12345'])
print(df)
# insert():在指定位置插入一个新列
# 参数:
# loc:新列要插入的位置
# column:要插入的列名
# value:要插入列值,可以列表、Series等
df.insert(1, 'tel', ['13812345678', '17712345678'])
print(df)
修改某一列的数据、修改列名以及修改某一列的数据类型
def test02():
df = pd.DataFrame({'name': ['zhangsan', 'lisi'], 'age': [20, 30], 'id': [1, 2]})
# 修改列,通过已存在的列名进行直接赋值即可修改该列的数据
df['age'] = [40, 50]
print(df)
# 对某一列进行算术运算,然后再重新赋值给该列
df['age'] = df['age'] - 10
print(df)
# 通过直接赋值修改列名
df.columns = ['A', 'B', 'C']
print(df)
# 通过rename方法修改列名
# 参数:
# columns:指定新列名,格式:dict,dict中key是旧列名,value是新列名
# columns属性和rename方法区别:columns在原数据上直接修改,rename是先备份一个副本,然后在副本上修改,不影响原数据
df = df.rename(columns={'A': 'name', 'B': 'age', 'C': 'id'})
print(df)
print(df['age'].dtype)
# astype():修改某一列的数据类型
df['age'] = df['age'].astype('str')
print(df['age'].dtype)
删除列
def test03():
df = pd.DataFrame({'name': ['zhangsan', 'lisi'], 'age': [20, 30], 'id': [1, 2]})
# drop():删除方法,既可以删除行,也可以删除列
# 参数:
# labels:要删除的列/行标签
# axis:指定按行或按列删除,axis=0表示按行删除,axis=1表示按列删除
# inplace:是否原地修改,如果为True则在原数据上进行删除,为False则先备份一个副本,然后在副本上进行删除,默认为False
df1 = df.drop(['id', 'age'], axis=1)
print(df1)
print(df)
df.drop(['id'], axis=1, inplace=True)
print(df)
行操作
使用loc方法获取一行或多行数据
def test01():
data = {
'A': [1, 2, 3, 4],
'B': [5, 6, 7, 8],
'C': [9, 10, 11, 12]
}
df = pd.DataFrame(data, index=['a', 'b', 'c', 'd'])
print(df)
# loc[]:根据行/列标签获取数据
# 获取单行数据,返回结果是行的Series,该对象的索引是DataFrame的列索引
print(df.loc['a'])
# 通过切片获取多行数据,(切片包含终止值),返回的结果是DataFrame
print(df.loc['a':'c'])
# 通过行标签和列标签获取数据,返回结果是一个标量
print(df.loc['a', 'B'])
print(df.loc['a':'c', 'B'])
print(df.loc[['a', 'c'], ['A', 'C']])
print(df.loc[df['B'] > 6, 'A'])
使用iloc方法获取一行或多行数据
def test02():
data = {
'A': [1, 2, 3, 4],
'B': [5, 6, 7, 8],
'C': [9, 10, 11, 12]
}
df = pd.DataFrame(data, index=['a', 'b', 'c', 'd'])
print(df)
# iloc[]:根据数组下标获取数据,loc[]是根据索引标签获取数据
# 获取单行数据
print(df.iloc[1])
# 通过切片获取多行数据,(不包含终止值)
print(df.iloc[0:2])
# 按行和列获取数据,结果是标量
print(df.iloc[0, 0])
DataFrame 对象的行切片操作
def test03():
data = {
'A': [1, 2, 3, 4],
'B': [5, 6, 7, 8],
'C': [9, 10, 11, 12]
}
df = pd.DataFrame(data, index=['a', 'b', 'c', 'd'])
print(df)
# DataFrame切片操作默认按行获取数据,但不能使用单标签或单下标获取
# 根据数组下标切片
print(df[0:2])
# 根据索引标签切片
print(df['a':'c'])
# 切片错误操作
# print(df['a'])
# print(df['a':'c', 'B'])
通过append函数和loc方法添加行
注意:DataFrame的append方法在1.4版本后被弃用
def test04():
data = {
'A': [1, 2, 3],
'B': [4, 5, 6]
}
df = pd.DataFrame(data, index=['a', 'b', 'c'])
# 创建一个示例 Series
new_row = pd.Series({'A': 7, 'B': 8}, name='d')
# 使用 append 追加 Series
df = df.append(new_row)
print(df)
def test05():
data = {
'A': [1, 2, 3, 4],
'B': [5, 6, 7, 8],
'C': [9, 10, 11, 12]
}
df = pd.DataFrame(data, index=['a', 'b', 'c', 'd'])
print(df)
# 通过loc添加新行
df.loc['e'] = [13, 14, 15]
print(df)
# 通过loc做修改行数据操作
df.loc['a'] += 1
print(df)
df.loc['e'] = df.loc['d'] + 1
print(df)
使用concat函数连接多个DataFrame对象
# concat():DataFrame连接
# 参数:
# objs:要连接的Dataframe的列表
# axis:连接方向:0-按行链接,1-按列连接
# ignore_index: 如果为True,则忽略原DataFrame的索引重新生成索引
# join:连接方式,outer-并集(默认),inner-交集
def test06():
data1 = {
'A': [1, 2, 3],
'B': [4, 5, 6]
}
df1 = pd.DataFrame(data1)
data2 = {
'A': [7, 8, 9],
'B': [10, 11, 12]
}
df2 = pd.DataFrame(data2)
df = pd.concat([df1, df2], axis=0, ignore_index=True)
print(df)
df = pd.concat([df1, df2], axis=1)
print(df)
def test07():
data1 = {
'A': [1, 2, 3],
'B': [4, 5, 6]
}
df1 = pd.DataFrame(data1)
# data2 = {
# 'A': [7, 8, 9],
# 'B': [10, 11, 12],
# 'C': [13, 14, 15]
# }
#
# df2 = pd.DataFrame(data2)
data2 = {
'A': [7, 8, 9, 1],
'B': [10, 11, 12, 1],
'C': [13, 14, 15, 1]
}
df2 = pd.DataFrame(data2)
df = pd.concat([df1, df2], axis=0, join='inner')
print(df)
df = pd.concat([df1, df2], axis=1, join='inner')
print(df)
行的删除操作
def test08():
data = {
'A': [1, 2, 3, 4],
'B': [5, 6, 7, 8],
'C': [9, 10, 11, 12]
}
df = pd.DataFrame(data, index=['a', 'b', 'c', 'd'])
df1 = df.drop(['a'], axis=0)
print(df1)
# drop():删除行或列
# 参数:
# index:要删除的行索引,格式是列表
# columns:要删除的列索引,格式是列表
# 如果指定了index或columns,labels会失效
df2 = df.drop(index=['a'])
print(df2)
df3 = df.drop(columns=['C'])
print(df3)
对行索引和列索引的调整以及新的索引的引入
import pandas as pd
def test01():
data = {
'A': [1, 2, 3],
'B': [4, 5, 6],
'C': [7, 8, 9]
}
df = pd.DataFrame(data, index=['a', 'b', 'c'])
# 调整行索引的顺序
df1 = df.reindex(index=['c', 'a', 'b'])
print(df1)
# 在原来行索引基础上添加一个行索引,添加的行索引对应的数据默认为NaN
df2 = df.reindex(index=['a', 'b', 'c', 'd'])
print(df2)
# 添加新的行索引,新索引会将原来索引对应的数据覆盖掉,以Nan填充
df3 = df.reindex(index=['e', 'f', 'g'])
print(df3)
# 调整列的顺序
df4 = df.reindex(columns=['C', 'A', 'B'])
print(df4)
# 在原来列标签的基础上添加新列
df5 = df.reindex(columns=['A', 'B', 'C', 'D'])
print(df5)
# 如果用新列完全替代原来的列索引,则数据被修改NaN
df6 = df.reindex(columns=['E', 'F', 'G'])
print(df6)
# 在原来行索引基础上添加新行,默认填充NaN,可以使用method进行Nan值的填充,ffill-前向填充,bfill-后向填充
df7 = df.reindex(index=['a', 'b', 'c', 'd'], method='ffill')
print(df7)
# 新行的值可以使用fill_value自定义数值进行填充
df8 = df.reindex(index=['a', 'b', 'c', 'd'], fill_value=0)
print(df8)
def test02():
df1 = pd.DataFrame({
'A': [1, 2, 3],
'B': [4, 5, 6]
}, index=['a', 'b', 'c'])
df2 = pd.DataFrame({
'A': [7, 8, 9],
'B': [10, 11, 12]
}, index=['b', 'c', 'd'])
# 行索引对齐,df1以df2作为参照,来对齐行索引(列索引一致的)
df3 = df1.reindex_like(df2)
print(df3)
# df1和df2行索引一致,对齐列索引
def test03():
df1 = pd.DataFrame({
'A': [1, 2, 3],
'B': [4, 5, 6]
}, index=['a', 'b', 'c'])
df2 = pd.DataFrame({
'B': [7, 8, 9],
'C': [10, 11, 12]
}, index=['a', 'b', 'c'])
df3 = df1.reindex_like(df2)
print(df3)
遍历DataFrame对象中的元素
data = {
'A': [1, 2, 3],
'B': [4, 5, 6]
}
df = pd.DataFrame(data, index=['a', 'b', 'c'])
# 遍历结果是列标签
for i in df:
print(i)
# iterrows():遍历行,返回行索引和行数据,行数据是Series对象
for index, row in df.iterrows():
print('------------')
print(index)
print(row)
# itertuples(): 遍历行,返回包含行数据的元组,推荐使用
# 参数:index:如果为False则不返回索引
for row in df.itertuples(index=False):
print(row)
for i in row:
print(i, end=' ')
print()
print('==========================')
# items():遍历列,返回包含列索引和列数据的迭代器
for col, values in df.items():
print(col)
print(values)
DataFrame对象的常用属性
data = {
'A': [1, 2, 3, 4],
'B': [5, 6, 7, 8]
}
df = pd.DataFrame(data, index=['a', 'b', 'c', 'd'])
# 转置
print(df.T)
# 返回包含行索引列表和列索引列表的列表
print(df.axes)
# 返回每列的数据类型
print(df.dtypes)
# 判断DataFrame是否为空,True表示为空,False表示不为空
print(df.empty)
# ndim:返回维度数
print(df.ndim)
# 返回形状
print(df.shape)
# 返回DataFrame的元素总数
print(df.size)
# 以numpy形式返回数组
print(df.values)
# 获取前n行,默认n=5
print(df.head(3))
# 获取后n行,默认n=5
print(df.tail(3))
使用sort_index方法或sort_values方法排序
import pandas as pd
def test01():
data = {
'B': [1, 2, 3],
'A': [4, 5, 6]
}
df = pd.DataFrame(data, index=['b', 'a', 'c'])
print(df)
# sort_index():按照索引标签进行排序
# 参数:
# axis:排序的方向,0-按行,1-按列,如果axis为None,按行排序
# ascending:表示是升序还是降序排序,True-升序,False-降序
# inplace:表示是否在原地修改,True-在原数据上排序,False-生成副本,在副本上排序
df1 = df.sort_index()
print(df1)
df2 = df.sort_index(axis=1)
print(df2)
df3 = df.sort_index(axis=0, ascending=False)
print(df3)
df.sort_index(axis=0, ascending=False, inplace=True)
print(df)
def test02():
data = {
'A': [3, 2, 1],
'B': [6, 5, 4],
'C': [9, 8, 7]
}
df = pd.DataFrame(data, index=['b', 'c', 'a'])
print(df)
# sort_values():根据一列或多列进行排序
# 参数:
# by:要排序的列或者列的列表
# ascending:升序或降序排序
# inplace:是否在原地修改
df1 = df.sort_values(by='A')
print(df1)
df2 = df.sort_values(by=['A', 'B'])
print(df2)
df = pd.DataFrame({
'Name': ['Alice', 'Bob', 'Charlie', 'David', 'Eve'],
'Age': [25, 30, 25, 35, 30],
'Score': [85, 90, 80, 95, 88]
})
# 根据Age和Score排序,Age列按照降序排序,如果Age列中的数据相同,则按照Score列升序排序
df1 = df.sort_values(by=['Age', 'Score'], ascending=[False, True])
print(df1)
pandas库中的常用统计函数
data = {
'A': [1, 2, 3, 4, 5],
'B': [10, 20, 30, 40, 50],
'C': [100, 200, 300, 400, 500]
}
df = pd.DataFrame(data)
# 统计每列的算数平均值
print(df.mean())
# 统计指定列的算数平均值
print(df['A'].mean())
# 指定多列,统计算数平均值
print(df[['A', 'B']].mean())
# 统计中位数
print(df.median())
# 统计每列的方差,默认是样本方差
print(df.var())
# 统计每列的标准方差
print(df.std())