Pandas基础学习分析处理nginx日志
Pandas 应用
Pandas 可以从各种文件格式比如 CSV、JSON、SQL、Microsoft Excel 导入数据。
Pandas 可以对各种数据进行运算操作,比如归并、再成形、选择,还有数据清洗和数据加工特征。
Pandas 广泛应用在学术、金融、统计学等各个数据分析领域。
Pandas 功能
Pandas 是数据分析的利器,它不仅提供了高效、灵活的数据结构,还能帮助你以极低的成本完成复杂的数据操作和分析任务。
Pandas 提供了丰富的功能,包括:
数据清洗:处理缺失数据、重复数据等。
数据转换:改变数据的形状、结构或格式。
数据分析:进行统计分析、聚合、分组等。
数据可视化:通过整合 Matplotlib 和 Seaborn 等库,可以进行数据可视化。
数据结构
Pandas的主要数据结构式Series(一维数据)与DataFrame(二维数据)
Series: 是一种类似于一维数组的对象,它由一组数据(各种Numpy的数据类型),以及一组与之相关的数据标签(索引)组成.
DataFrame: 是一个表格型,它含有一组有序的列,每列可以是不同的值类型,DataFrame 既有行索引也有列索引,它可以被看做由 Series 组成的字典(共同用一个索引)。
这里详细解释下:
- Series:定义: 一维数组,类似与带有标签的列表.
特点:
每个元素都有唯一的标签(索引);可以存储任意数据类型(整数,小数,布尔);
Series可以存储多种不同数据类型的元素.
series的大小在创建之后是不变的,但是可以通过append或者delete相关函数修改.
Series 可以包含缺失数据,Pandas 使用NaN(Not a Number)来表示缺失或无值
创建方式:
创建Series的完整函数解释:
pandas.Series(data=None, index=None, dtype=None, name=None, copy=False, fastpath=False)
data: Series的数据部分,可以是列表,数组,字典等.不提供会创建一个空Series.
index:Series 的索引部分,用于对数据进行标记。可以是列表、数组、索引对象等。如果不提供此参数,则创建一个默认的整数索引。
dtype:指定 Series 的数据类型。可以是 NumPy 的数据类型,例如 np.int64、np.float64 等。如果不提供此参数,则根据数据自动推断数据类型。
name:Series 的名称,用于标识 Series 对象。如果提供了此参数,则创建的 Series 对象将具有指定的名称。
copy:是否复制数据。默认为 False,表示不复制数据。如果设置为 True,则复制输入的数据。
fastpath:是否启用快速路径。默认为 False。启用快速路径可能会在某些情况下提高性能。
# 日志格式
# 192.168.113.187 - - [03/Apr/2025:22:41:45 +0800] "GET /app/test/index.html HTTP/2.0" 200 655346397 "-" "com.apple.appstored/1.0 iOS/18.3.1 model/iPhone13,4 hwp/t8101 build/22D72 (6; dt:231) AMS/1" "-"import pandas as pd# 从列表中创建
s =pd.Series([1,3,5,7,9])
print(s)sites = {1: "Google", 2: "Runoob", 3: "Wiki"}
# 这里通过字典方式定义,key就是变成了索引值
myvar = pd.Series(sites)print(myvar)## 这里就是将里列表原本存在数据结构进行规范,定义为Series.
# 常用操作:
# 访问元素:s[0] 或 s['a']# 切片:s[1:3]# 数学运算:s + 10
print(s+10) #对列表中的每个值进行了运算
#输出:
# 0 11
# 1 13
# 2 15
# 3 17
# 4 19
# dtype: int64
# 统计函数:s.mean()、s.max()
- DataFrame
定义: 二维表格型数据结构,类似与表格和sql表
特点: 每列可以是不同的数据类型(整数,字符串,等); 每行索引和列索引
构造方法:
pandas.DataFrame(data=None, index=None, columns=None, dtype=None, copy=False)
data:DataFrame 的数据部分,可以是字典、二维数组、Series、DataFrame 或其他可转换为 DataFrame 的对象。如果不提供此参数,则创建一个空的 DataFrame。
index:DataFrame 的行索引,用于标识每行数据。可以是列表、数组、索引对象等。如果不提供此参数,则创建一个默认的整数索引。
columns:DataFrame 的列索引,用于标识每列数据。可以是列表、数组、索引对象等。如果不提供此参数,则创建一个默认的整数索引。
dtype:指定 DataFrame 的数据类型。可以是 NumPy 的数据类型,例如 np.int64、np.float64 等。如果不提供此参数,则根据数据自动推断数据类型。
copy:是否复制数据。默认为 False,表示不复制数据。如果设置为 True,则复制输入的数据。# 从字典创建
data = {'Name': ['Alice', 'Bob', 'Charlie'],'Age': [25, 30, 35],'City': ['New York', 'Los Angeles', 'Chicago']
}
df =pd.DataFrame(data)
# print(df)
# 从列表创建
data1 = [['Alice', 25, 'New York'],['Bob', 30, 'Los Angeles'],['Charlie', 35, 'Chicago']
]
df1=pd.DataFrame(data1,columns=['Name','Age','City'])# print(df1)
#访问列:
# print(df1['Name'])
#访问行
# print(df.loc[0])
#添加列
df['Salary'] = [50000, 60000, 70000]
print(df)
# 添加新行到末尾使用concat函数,想当于将两个DataFrame类型进行拼接
new_row = pd.DataFrame({'Name': ['wcp'], 'Age': [25], 'City': ['cd']})
df = pd.concat([df, new_row], ignore_index=True)
print(df)
dataframe的用法比较多的,在实际应用中较多场景,具体用法可参考:https://www.runoob.com/pandas/pandas-dataframe.html
简单应用,使用pandas统计分析nginx请求日志数据
import pandas as pdimport re## 定义日志格式的正则处理
log_pattern = re.compile(r'(?P<ip>\S+) - - \[(?P<time>[^\]]+)\] "(?P<method>\S+) (?P<path>\S+) (?P<protocol>[^"]+)" (?P<status>\d{3}) (?P<size>\d+|-) "(?P<referrer>[^"]*)" "(?P<user_agent>[^"]*)" "(?P<http_x_forwarded_for>[^"]*)"'
)
# ip-- 间 请求方法 路径 协议 状态码 响应大小## 读取日志文件
log_file="access.log"
logs=[]with open(log_file,'r') as file:for line in file: # 按行读取match=log_pattern.match(line)# print(match.groupdict()) ## 数据分组格式化if match:logs.append(match.groupdict())## 将数据加载到Pandas DataFrame
df = pd.DataFrame(logs)df['time']=pd.to_datetime(df['time'],format='%d/%b/%Y:%H:%M:%S %z')
df['size'] = pd.to_numeric(df['size'], errors='coerce')## 统计请求total_request = len(df)
print(f"总请求数: {total_request}")status_counts = (df['status'].value_counts(normalize=True) * 100).round(2)
print("\n状态码比率:")
print(status_counts)
# 统计请求路径的占比
path_counts = (df['path'].value_counts(normalize=True) * 100).round(2) # 转换为百分比
print("\n请求路径占比:")
print(path_counts)# 统计请求路径的占比
path_counts = (df['ip'].value_counts(normalize=True) * 100).round(2) # 转换为百分比
print("\n请求客户端ip占比:")
print(path_counts)
使用pandas的分析班级平均成绩,并展示图表
# -*- coding: utf-8 -*-
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from bokeh.plotting import figure, show, output_fileplt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus'] = False# 导入 CSV 文件
df = pd.read_csv('student.csv')# 数据分析
class_avg_score = df.groupby('Class')['Score'].mean()
gender_avg_score = df.groupby('Gender')['Score'].mean()
class_count = df['Class'].value_counts()
score_distribution = df['Score'].describe()# 打印分析结果
print("每个班级的平均成绩:")
print(class_avg_score)
print("\n每个性别的平均成绩:")
print(gender_avg_score)
print("\n每个班级的学生人数:")
print(class_count)
print("\n成绩分布:")
print(score_distribution)# 设置主题
sns.set_theme(style="whitegrid")# 绘制班级平均成绩柱状图
plt.figure(figsize=(8, 5))
sns.barplot(x=class_avg_score.index, y=class_avg_score.values, palette="viridis")
plt.title('每个班级的平均成绩')
plt.xlabel('班级')
plt.ylabel('平均成绩')
plt.show()#
# # 绘制性别平均成绩柱状图
# plt.figure(figsize=(8, 5))
# sns.barplot(x=gender_avg_score.index, y=gender_avg_score.values, palette="magma")
# plt.title('每个性别的平均成绩')
# plt.xlabel('性别')
# plt.ylabel('平均成绩')
# plt.show()
#
# # 绘制班级学生人数饼图
# plt.figure(figsize=(6, 6))
# plt.pie(class_count, labels=class_count.index, autopct='%1.1f%%', colors=sns.color_palette("pastel"))
# plt.title('班级学生人数分布')
# plt.show()
#
# # 绘制班级成绩分布箱线图
# plt.figure(figsize=(8, 5))
# sns.boxplot(x='Class', y='Score', data=df, palette="Set2")
# plt.title('班级成绩分布')
# plt.xlabel('班级')
# plt.ylabel('成绩')
# plt.show()
student.csv
Name,Age,Gender,Score,Class
Alice,18,Female,95,Class A
Bob,17,Male,88,Class A
Charlie,18,Male,92,Class A
Diana,17,Female,90,Class B
Eva,18,Female,85,Class B
Frank,17,Male,78,Class B
Grace,18,Female,96,Class A
Henry,17,Male,89,Class B
Ivy,18,Female,91,Class A
Jack,17,Male,84,Class B
Alice,16,Female,92,Class A
Bob,17,Male,78,Class C
Charlie,18,Male,88,Class B
Diana,16,Female,95,Class A
Ethan,17,Male,81,Class B
Fiona,16,Female,76,Class C
George,18,Male,85,Class A
Hannah,17,Female,90,Class B
Ian,16,Male,83,Class C
Jenny,17,Female,79,Class A
Kevin,18,Male,87,Class B
Lisa,16,Female,93,Class C
Michael,17,Male,82,Class A
Nina,16,Female,77,Class B
Oliver,18,Male,86,Class C
Paula,17,Female,91,Class A
Quinn,16,Male,80,Class B
Rachel,17,Female,75,Class C
Samuel,18,Male,84,Class A
Tina,16,Female,89,Class B