赞
踩
Pandas 是一个开源的第三方 Python 库,从 Numpy 和 Matplotlib 的基础上构建而来,享有数据分析
“三剑客之一”的盛名(NumPy
、Matplotlib
、Pandas
)。提供了快速、灵活、明确的数据结构,旨在简单、直观地处理关系型、标记型数据。B站视频。
pip install openpyxl
pip install pandas
# 使用阿里云镜像安装
pip install pandas -i https://mirrors.aliyun.com/pypi/simple/
# 引入模块,简写成pd(这是大家都采取不成文的习惯)
import pandas as pd
要学Pandas就必须要先了解Pandas的两大数据结构:Series 和 DataFrame。
索引index
➕值values
组成。[索引]
来获取对应的数据。NaN
(Not a Number)。列表list构建
# 表示一列数据(第一列表示默认自带的索引从0开始),也可以通过参数index=[]自己设置索引 series1 = pd.Series(['张无忌', '孙悟空', '武大郎']) print(series1) 0 张无忌 1 孙悟空 2 武大郎 dtype: object # 武大郎 print(series1[2]) # index=keys(),RangeIndex(start=0, stop=3, step=1) print(series1.index, series1.keys()) # ['张无忌' '孙悟空' '武大郎'] print(series1.values) # 显式设置索引列 series1 = pd.Series(['张无忌', '孙悟空', '武大郎'], index=['a', 'b', 'c']) print(series1)
字典构建
series2 = pd.Series({'a': '张无忌', 'b': '孙悟空', 'c': '武大郎'})
print(series2)
a 张无忌
b 孙悟空
c 武大郎
dtype: object
# 武大郎
print(series2['c'])
series1 = pd.Series({'a': 1, 'b': 2, 'c': 3}) series2 = pd.Series({'a': 10, 'b': 20, 'c': 30, 'd': 40}) print(series1 + series2) a 11.0 b 22.0 c 33.0 d NaN dtype: float64 # fill_value: 表示索引不存在按照默认值0算 add = series1.add(series2, fill_value=0) print(add) a 11.0 b 22.0 c 33.0 d 40.0 dtype: float64
pd.Series(data, index, name)
DataFrame类似于一个二维数组,可以看做成表格,由行和列组成。表格中的每一行每一列都是Series数据结构。
Series是由index索引➕values值组成。对于列index是指的列索引,对于行index是指的行索引(列名)。
# data: 每一行数据 # columns:列名 # index:自定义索引列,默认是数字从0开始,也可以显式指定 data = [('猛男', 30, '男'), ('舔狗', 50, '男'), ('细狗', 18, '男')] df = pd.DataFrame(data, columns=('姓名', '年龄', '性别')) print(df) 姓名 年龄 性别 0 猛男 30 男 1 舔狗 50 男 2 细狗 18 男 print(df['姓名']) # 每一列也是<class 'pandas.core.series.Series'> print(type(df['姓名'])) # 获取指定的行,没行也是一个Series ['猛男' 30 '男'] <class 'pandas.core.series.Series'> print(df.loc[0].values, type(df.loc[0])) # 行的index是列名 # Index(['姓名', '年龄', '性别'], dtype='object') print(df.loc[0].index)
Series作为行还是作为列主要取决于在构建DataFrame时是使用字典dict(列)还是列表list(行)。
作为列
# 方式一:value是list类型 # dtype指定列的数据类型,注意:只能统一指定,不能按照列来指定 df = pd.DataFrame({'姓名': ['猛男', '舔狗', '细狗'], '年龄': [10, 20, 30], '性别': ['男', '男', '男']}, index=[1, 2, 3], dtype=str) # 单独指定列的数据类型 df['姓名'] = df['姓名'].astype(str) df['年龄'] = df['年龄'].astype(float) df['性别'] = df['性别'].astype(str) print(df) 姓名 年龄 性别 1 猛男 10.0 男 2 舔狗 20.0 男 3 细狗 30.0 男 # 方式二:value是Series对象 # 作为列,index表示列索引,name就表示列名 c1 = pd.Series(['猛男', '舔狗', '细狗'], index=[1, 2, 3], name='姓名') c2 = pd.Series([10, 20, 30], index=[1, 2, 3], name='年龄') c3 = pd.Series(['男', '男', '男'], index=[1, 2, 3], name='性别') df = pd.DataFrame({c1.name: c1, c2.name: c2, c3.name: c3}) print(df) 姓名 年龄 性别 1 猛男 10 男 2 舔狗 20 男 3 细狗 30 男
作为行
# 作为行,index表示列名,name就表示列索引
header = ['姓名', '年龄', '性别']
r1 = pd.Series(['猛男', 10, '男'], index=header, name='a')
r2 = pd.Series(['舔狗', 20, '男'], index=header, name='b')
r3 = pd.Series(['细狗', 30, '男'], index=header, name='c')
df = pd.DataFrame([r1, r2, r3])
df.to_excel('temp.xlsx', index=False, header=False)
print(df)
姓名 年龄 性别
a 猛男 30 男
b 舔狗 50 男
c 细狗 18 男
属性或方法 | 描述 |
---|---|
列索引操作 | |
df.columns 和 df.keys() | 获取表头列索引对象 Index(['姓名', '年龄'], dtype='object') |
df.columns.values | 获取表头列索引对象的values列表 ['姓名' '年龄'] |
df.columns = ['Name', 'Age'] | 重新设置表头 |
df.index | 获取所有列索引 RangeIndex(start=0, stop=3, step=1) |
获取部分行 | |
df.values | 获取所有列索引列表 [0 1 2] |
df.values | 获取所有行数据,返回值类型<class ‘numpy.ndarray ’> [[‘张三’, 20],[‘李四’, 25],[‘王五’, 30]] |
len(df) | 获取数据行数(不算表头) |
df.shape | 获取数据行数和列数tuple (3, 2) 3行2列 |
df.head(n) | 获取前n行数据,返回值类型DataFrame ,n默认为5 |
df.tail(n) | 获取最后n行数据,返回值类型DataFrame ,n默认为5 |
df.sample(n) | 随机获取n行数据,返回值类型DataFrame |
获取指定行 | |
df.loc[row_index] | df.loc[1]:获取指定行的Series 对象 |
df.loc[[row_index, row_index2]] | df.loc[[1, 2]]:获取指定的多个行索引数据,返回值类型为 DataFrame |
df.iloc[row_index] | df.iloc[1]: 获取指定行的Series 对象,和df.loc[row_index]结果一样 |
df.loc[df['列名'] == '列值'] | df.loc[df[‘姓名’] == ‘李四’] : 返回满足条件的行,返回值类型 DataFrame |
df.loc[df['姓名'] == '李四'].loc[df['性别'] == '男'] | 多个loc表示and关系 |
获取指定列 | |
df['列名'] | df[‘姓名’] :获取指定列的数据,返回值类型 Series |
df[['列名1', '列名2']] | df[[‘姓名’, ‘年龄’]] : 获取多列数据,返回值类型 DataFrame |
获取指定行指定列 | |
df.loc[row_index, '列名'] | df.loc[1, ‘姓名’] :获取指定行指定列的单元格值,返回值str |
df.loc[row_index, ['列名1', '列名2']] | df.loc[1, [‘姓名’, ‘性别’]] : 获取某行的多列值,返回值类型 Series , df.loc[1, :] 返回指定行的所有列 |
df.at[row_index, '列名'] | df.at[1, ‘姓名’] = df.loc[1, ‘姓名’] 获取指定指定列的值,返回值str ,只是loc支持多列 |
df['列名'].at[row_index] | df[‘姓名’].at[1] : 获取指定列的指定行的值,返回值str |
import pandas as pd df = pd.DataFrame([('张三', 20), ('李四', 25), ('王五', 30)], columns=('姓名', '年龄')) # Index(['姓名', '年龄'], dtype='object') print(df.columns, df.keys()) # ['姓名' '年龄'] print(df.columns.values) # 重新设置表头 df.columns = ['Name', 'Age'] print(df) Name Age 0 张三 20 1 李四 25 2 王五 30
df = pd.DataFrame([('张三', 20, '男'), ('李四', 25, '男'), ('王五', 30, '男')],
columns=('姓名', '年龄', '性别'))
print(df['姓名'] == '李四')
0 False
1 True
2 False
Name: 姓名, dtype: bool
# 返回值类型为<class 'pandas.core.series.Series'>
print(type(df['姓名'] == '李四'))
df = pd.DataFrame([('张三', 20, '男'), ('李四', 25, '男'), ('王五', 30, '男')],
columns=('姓名', '年龄', '性别'))
print(df.loc[df['姓名'] == '李四'])
姓名 年龄 性别
1 李四 25 男
# <class 'pandas.core.frame.DataFrame'>
print(type(df.loc[df['姓名'] == '李四']))
print(df.loc[df['姓名'] == '李四'].loc[df['性别'] == '男'])
pandas将索引列index
和数据列columns
作为两个不同的概念来对待的。
df.set_index(“索引列名”, inplace=True):用于将某列作为索引列,inplace=True表示替换默认的索引列。
import pandas as pd df = pd.DataFrame([(1, '张三', 20, '男'), (2, '李四', 25, '男'), (3, '王五', 30, '男')], columns=('id', '姓名', '年龄', '性别')) print(df) id 姓名 年龄 性别 0 1 张三 20 男 1 2 李四 25 男 2 3 王五 30 男 # 设置id为索引列,inplace=True表示替换默认的索引列 df.set_index('id', inplace=True) print(df) 姓名 年龄 性别 id 1 张三 20 男 2 李四 25 男 3 王五 30 男 # Int64Index([1, 2, 3], dtype='int64', name='id') print(df.index)
file = pd.ExcelFile('订单.xlsx')
names = file.sheet_names
sheet_name:list[IntStrT]
指定读取的sheet,默认为第一个,可以通过指定sheet的名字或者索引(从0开始),多个使用列表。dict[IntStrT, DataFrame]
:key表示sheet的索引,DataFrame表示每个Sheet对应的数据。读取所有sheet的每行数据。
import pandas as pd
excel = pd.read_excel('订单.xlsx', sheet_name=[0, 1], skiprows=0)
for sheet, df in excel.items():
for row in df.values:
print(row)
import pandas as pd
csv = pd.read_csv('test.csv', index_col='id')
tsv = pd.read_csv('test.tsv', sep='\t', index_col='id')
txt = pd.read_csv('test.txt', sep='|', index_col='id')
import pandas as pd
import pymysql
import sqlalchemy
pymysql.install_as_MySQLdb()
sql = 'select id, username, gender from user'
conn = sqlalchemy.create_engine('mysql://root:root123@127.0.0.1:3306/test?charset=utf8')
user = pd.read_sql(sql, conn)
print(user)
import pandas as pd
header = ('姓名', '年龄')
rows = [('张三', 20), ('李四', 25)]
df = pd.DataFrame(rows, columns=header)
df.to_excel('test.xlsx', sheet_name='Sheet1', index=False)
import pandas as pd
header1 = ('姓名', '年龄')
rows1 = [('张三', 20), ('李四', 25)]
df = pd.DataFrame(rows1, columns=header1)
header2 = ('姓名', '年龄')
rows2 = [('虚竹', 20), ('梦姑', 25)]
df2 = pd.DataFrame(rows2, columns=header2)
writer = pd.ExcelWriter('test1.xlsx')
df.to_excel(writer, sheet_name='Sheet1', index=False)
df2.to_excel(writer, sheet_name='Sheet2', index=False)
writer.close()
import pandas as pd sheet1 = pd.DataFrame([(1, '张三'), (2, '李四'), (3, '王五')], columns=('id', 'name')) sheet2 = pd.DataFrame([(4, '赵六'), (5, '冯七')], columns=('id', 'name')) # 追加Sheet drop=True 放弃旧的index # users = sheet1.append(sheet2).reset_index(drop=True) users = pd.concat([sheet1, sheet2]).reset_index(drop=True) # 追加一行 user = pd.Series({'id': 6, 'name': '六六'}) users = users.append(user, ignore_index=True) # 修改单元格数据 users.at[2, 'name'] = '隔壁老王' # 整行替换 user = pd.Series({'id': 66, 'name': '六六'}) users.iloc[5] = user # 插入一行 part1 = users[:3] insert = pd.Series({'id': 99, 'name': '插队狗'}) part2 = users[3:] users = part1.append(insert, ignore_index=True).append(part2).reset_index(drop=True) # 删除多行 index也可以是range users.drop(index=[0, 1], inplace=True) # 通过切片删除 users.drop(index=users[3:5].index, inplace=True) # 根据条件移除 where = users.loc[users['id'] == 3] users.drop(index=where.index, inplace=True) print(users)
import pandas as pd import numpy as np sheet1 = pd.DataFrame([(1, '张三'), (2, '李四'), (3, '王五')], columns=('id', 'name')) sheet2 = pd.DataFrame([(1, 10), (2, 20), (3, 30)], columns=('id', 'age')) # 拼接列 all = pd.concat([sheet1, sheet2], axis=1) print(all) # 追加一列 sheet1['no'] = np.arange(1000, len(sheet1) + 1000) # 删除列 sheet1.drop(columns=['name'], inplace=True) # 插入一列 sheet1.insert(1, column='age', value=np.repeat(18, len(sheet1))) # 重命名列名 sheet1.rename(columns={'id': 'ID', 'no': 'NO'}, inplace=True) # 删除任意列种有NaN的行 sheet1.dropna(inplace=True) print(sheet1)
import pandas as pd
df = pd.DataFrame([(1, 10, 0.1), (2, 20, 0.2), (3, 15, 0.15)], columns=('id', 'price', 'discount'))
df.set_index('id', inplace=True)
df = df.loc[df['price'].apply(lambda x: 15 <= x <= 30)] \
.loc[df['discount'].apply(lambda x: x > 0.15)]
# 简写形式:可以直接通过 df.price = df['price']
df = df.loc[df.price.apply(lambda x: 15 <= x <= 30)].loc[df.discount.apply(lambda x: x > 0.15)]
print(df)
计算某列的值:Series整列直接相乘。
import pandas as pd
df = pd.DataFrame([(1, 10, 0.1), (2, 20, 0.2)], columns=('id', 'price', 'discount'))
df.set_index('id', inplace=True)
# <class 'pandas.core.series.Series'>
# Python是可以对类进行计算符重写的,所以这里可以加减相乘等计算
print(type(df['price']))
df['amount'] = df['price'] * df['discount']
print(df)
计算某列的值:单元格值 * 单元格值。这种方式可以对每一行做特殊处理。
import pandas as pd
df = pd.DataFrame([(1, 10, 0.1), (2, 20, 0.2)], columns=('id', 'price', 'discount'))
df.set_index('id', inplace=True)
for i in df.index:
df.at[i, 'amount'] = df.at[i, 'price'] * df.at[i, 'discount']
通过函数计算某列的值。
import pandas as pd
df = pd.DataFrame([(1, 10, 0.1), (2, 20, 0.2)], columns=('id', 'price', 'discount'))
df.set_index('id', inplace=True)
for i in df.index:
# apply(函数名|匿名函数)
df['amount'] = df['price'].apply(lambda x: x + 2)
print(df)
复杂计算列
import pandas as pd
def calc(row):
return (row['p1'] * 2 + row['p2'] * 3)/2 + row['id']
sheet1 = pd.DataFrame([(1, 20, 30), (2, 30, 40)], columns=('id', 'p1', 'p2'))
sheet1['p3'] = sheet1.apply(calc, axis=1)
print(sheet1)
import pandas as pd
df = pd.DataFrame([(1, 10, 0.1), (2, 20, 0.2), (3, 15, 0.15)], columns=('id', 'price', 'discount'))
df.set_index('id', inplace=True)
# inplace=True表示影响原来的df的值, ascending=True表示升续
# df.sort_values(by='price', inplace=True, ascending=True)
# 多个值排序:price asc, discount desc
df.sort_values(by=['price', 'discount'], inplace=True, ascending=[True, False])
print(df)
import pandas as pd
# 每行求和、求平均值
df = pd.DataFrame([(1, '张三', 80, 90), (2, '李四', 70, 88), (3, '王五', 90, 98)], columns=('id', 'name', 'chinese', 'english'))
row = df[['chinese', 'english']]
df['sum'] = row.sum(axis=1)
df['avg'] = row.mean(axis=1)
print(df)
# 每列就平均值
col_avg = df[['chinese', 'english', 'sum', 'avg']].mean()
col_avg['id'] = ''
col_avg['name'] = 'summary'
new_df = df.append(col_avg, ignore_index=True)
print(new_df)
import pandas as pd sheet1 = pd.DataFrame([(1, '张三'), (2, '李四'), (3, '王五')], columns=('id', 'name')) sheet1.set_index('id', inplace=True) sheet2 = pd.DataFrame([(1, 88), (2, 99)], columns=('id', 'score')) sheet2.set_index('id', inplace=True) # how: 表示连接方式, left/right/inner # left_on:表示左表关联的字段,right_on表示右表关联的字段,on:表示左右两个表的关联字段相同 # 表示如果值为NaN就设置指定的值 # student_score = sheet1.merge(sheet2, how='left', on='id').fillna(0) # student_score = sheet1.merge(sheet2, how='left', left_on='id', right_on='id').fillna(0) # merge如果不设置on、left_on、right_on 会报错而join函数会自动识别每个sheet的index只作为关联字段 student_score = sheet1.merge(sheet2, how='left', left_on=sheet1.index, right_on=sheet2.index).fillna(0) # 设置列的类型,数字默认是float student_score.score = student_score.score.astype(int) # print(student_score) student_score2 = sheet1.join(sheet2, how='left').fillna(0) student_score2.score = student_score2.score.astype(int) print(student_score2)
import pandas as pd
# 去除重复行
df = pd.DataFrame([(1, '张三', 80, 90), (2, '李四', 70, 88), (3, '张三', 90, 98), (4, '张三', 90, 98)],
columns=('id', 'name', 'chinese', 'english'))
# 指定重复数据依据的字段, 如果重复可以选择留下first或者last
df.drop_duplicates(subset=['name'], inplace=True, keep='first')
print(df)
import pandas as pd
df = pd.DataFrame([(1, '张三', 80, 90), (2, '李四', 70, 88), (3, '张三', 90, 98), (4, '张三', 90, 98)],
columns=('id', 'name', 'chinese', 'english'))
# True表示重复
duplicated = df.duplicated(subset=['name'])
# 表示是否有True值
print(duplicated.any())
# 找出重复的行
duplicated = duplicated[duplicated==True]
print(df.iloc[duplicated.index])
import pandas as pd df = pd.DataFrame([ (1, '上海', '2021-03-01', 80), (2, '上海', '2022-05-01', 59), (3, '上海', '2022-07-01', 80), (4, '上海', '2022-08-01', 59), (5, '郑州', '2021-10-01', 50), (6, '郑州', '2021-10-01', 80), (7, '郑州', '2022-10-01', 30), (8, '郑州', '2022-10-01', 20) ], columns=('id', 'city', 'date', 'score')) # 添加一列 df['year'] = pd.DatetimeIndex(df['date']).year groups = df.groupby(['city', 'year']) sum = groups['score'].sum() count = groups['id'].count() pd2 = pd.DataFrame({'sum': sum, 'count': count}) print(pd2)
import pandas as pd from datetime import date, timedelta def add_month(start_date, month): yd = month // 12 m = start_date.month + month % 12 if m != 12: yd += m // 12 m = m % 12 return date(start_date.year + yd, m, start_date.day) books = pd.read_excel('book.xlsx', skiprows=3, usecols='C:F', dtype={'ID': str, 'InStore': str, 'Date': str}) start = date(2022, 10, 30) for i in books.index: books['ID'].at[i] = i + 1 books['InStore'].at[i] = 'Yes' if i % 2 == 0 else 'No' # 加天 books.at[i, 'Date'] = start + timedelta(days=i) # 加年 #books.at[i, 'Date'] = date(start.year + 1, start.month, start.day) # 加月 #books.at[i, 'Date'] = add_month(start, i) print(books) books.set_index('ID', inplace=True) books.to_excel('book2.xlsx')
import pandas as pd
# 数据分列
df = pd.DataFrame([(1, '张 三'), (2, '李 四'), (3, '王 五')], columns=('id', 'name'))
tmp = df['name'].str.split(" ",expand=True)
# 列不存在则添加
df['first'] = tmp[0]
df['last'] = tmp[1]
print(df)
import pandas as pd
def check_age(row):
if row.age < 0 or row.age > 150:
print(f'{row.id} : {row.age} 数据非法')
pd = pd.DataFrame([(1, '张三', 30), (2, '李四', -1), (3, '王五', 1000)], columns=('id', 'name', 'age'))
# axis = 1: 表示从左到右(逐行校验)
# axis = 0: 表示从上到下(逐列校验)
pd.apply(check_age, axis=1)
import pandas as pd
pd.options.display.max_columns = 999
df = pd.DataFrame([(1, '张三', 90), (2, '李四', 70), (3, '张三', 90)],
columns=('id', 'name', 'chinese'))
df.set_index('id', inplace=True)
transpose = df.transpose()
print(transpose)
import pandas as pd
import numpy as np
df = pd.DataFrame([
(1, '上海', '2021-03-01', 80), (2, '上海', '2022-05-01', 59),
(3, '上海', '2022-07-01', 80), (4, '上海', '2022-08-01', 59),
(5, '郑州', '2021-10-01', 50), (6, '郑州', '2021-10-01', 80),
(7, '郑州', '2022-10-01', 30), (8, '郑州', '2022-10-01', 20)
], columns=('id', 'city', 'date', 'score'))
# 添加一列
df['year'] = pd.DatetimeIndex(df['date']).year
table = df.pivot_table(columns='year', values='score', aggfunc=np.sum, index='city')
print(table)
from openpyxl import load_workbook wb = load_workbook(file_path) ws = wb['工作表1'] ws.title = '表1' wb.save(file_path) wb.close() // 修改所有sheet名称, 重新读取再保存 file_path = 'test.xlsx' file = pd.ExcelFile(file_path) writer = pd.ExcelWriter(file_path) for name in file.sheet_names: df = pd.read_excel(file_path, sheet_name=name) df.to_excel(excel_writer=writer, sheet_name=name + '2', header=False, index=False) writer.save() writer.close() from openpyxl import load_workbook wb = load_workbook(file_path) sheetnames = wb.sheetnames for sheetname in sheetnames: ws = wb[sheetname] ws.title = sheetname + '1' wb.save(file_path) wb.close()
import pandas as pd import matplotlib.pyplot as plt from scipy.stats import linregress # pip install matplotlib # pip install scipy df = pd.DataFrame([ ('2022-01-01', 20), ('2022-02-01', 30), ('2022-03-01', 50), ('2022-04-01', 40), ('2022-05-01', 60), ('2022-06-01', 80), ('2022-07-01', 90), ('2022-08-01', 80), ('2022-09-01', 130), ('2022-10-01', 120), ('2022-11-01', 150), ('2022-12-01', 110)], columns=('month', 'amount')) slope, intercept, r, p, std_err = linregress(df.index, df.amount) exp = df.index * slope + intercept # 预测值 print(slope * 35 + intercept) plt.scatter(df.index, df.amount) plt.plot(df.index, exp, color='orange') plt.title(f'y={slope} * x + {intercept} ') plt.xticks(df.index, df.month, rotation=90) plt.tight_layout() plt.show()
条件格式
import pandas as pd # 需要在jupyer环境下运行 jupyter notebook def lowcolor(x): color = 'red' if x < 60 else 'black' return f'color:{color}' def highcolor(col): return ['background-color:line' if s == col.max() else 'background-color:white' for s in col] df = pd.DataFrame([ ('张三', 20, 50, 70), ('李四', 80, 90, 90), ('王五', 40, 30, 80), ('赵六', 90, 80, 30), ('冯七', 70, 80, 50)], columns=('name', 'china', 'english', 'math')) df.style.applymap(lowcolor, subset=['china', 'english']) \ .applymap(highcolor, subset=['china', 'english']) df.style.bar(color='green', subset=['math'])
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。