day 1:数据可视化|实践:pandas库绘图以及数据清洗

实 验 目 的: 

1、掌握pandas库的series和dataframe的增、删、改、查。

2、掌握灵活获取csv文件中的单元格、行、列数据。

3、掌握pandas的简单绘图。

4、掌握pandas进行数据的清晰。

实 验 环 境:

设备:PC机,建议个人PC,实验室计算机重启后不保留之前实验;

操作系统:Windows

软件:Anaconda3-2020.11-Windows-x86_64.exe(集成开发环境)

编程语言:python

OS:Windows

python:3.8.5

Pyecharts:1.8.1及以上版本

实 验 内 容 及 过 程: 

任务一

Pandas提供了两种主要的数据结构Series和DataFrame。两者分别适用于一维和多维数据,是在Numpy的ndarray基础上加入了索引而形成的高级数据结构。

6.1.1 特殊包

导入下面两个包,以免每次运行都出现警告。

import pyecharts

pyecharts.globals._WarningControl.ShowWarning = False

import warnings

warnings.filterwarnings('ignore')


或者读取csv文件的时候进行设置

datacsv2=pd.read_csv("data/2/数据2.csv",encoding="gbk",low_memory=False,index_col="商品")

6.1.2 汉字和负号的设置(重要)

import matplotlib.pyplot as plt

plt.rcParams["font.sans-serif"]="SimHei"#设置字体,防止中文乱码

plt.rcParams["axes.unicode_minus"]=False  #防止负号乱码

6.1.3 Series序列

  Series 用于保存一维数据,主要包含index和value。其基本语法如下:

       pandas.Series(data=None, index=None, name=None)

参数说明如下:

data:接收array或dict。表示接收的数据。默认为None。

index:接收array或list。表示索引,必须与数据长度相同

name:接收string或list。表示Series对象的名称。默认为None

 详细的序列的增删改查合并等操作参考课件。    

Series的学习网址:Series — pandas 2.2.3 documentation 

6.1.4 DataFrame数据框

DataFrame,,主要包含index、value、columns语法格式如下:

pandas.DataFrame(data=None, index=None, columns=None, dtype=None, copy=False)

参数说明如下所示:

data:接收ndarray、dict、list或DataFrame。表示输入数据。默认为None。

index:接收Index,ndarray。表示索引。默认为None。

columns:接收Index,ndarray。表示列标签(列名)。默认为None。

详细的数据框的增、删、改、查、合并、条件选取等操作参考课件。    

数据框学习10分钟https://pandas.pydata.org/docs/user_guide/10min.html   

6.1.5 pandas读取外部文件

Pandas库读取CSV、Excel等外部文件

详细的pandas读取文件部分的操作参考课件

6.2 任务二(验证性操作)!

6.2.1 pandas验证操作

1、验证以下代码,并将结果附截图

import pandas as pd

A=[1,3,6,4,9,10,15]

weight=[67,66,83,68,79,88]

sex=['女','男','男','女','男', '男']

S1=pd.Series(A)#构建S1序列

print(S1)

S2=pd.Series(weight)#构建S2序列

print(S2)

S3=pd.Series(sex)#构建S3序列

print(S3)

print(S3[1])#或print(S3.iloc[1]

print(S2[2])#或print(S2.iloc[2])



#Series 提供了两种访问元素的方法:loc(基于标签的索引)和 iloc(基于位置的索引)

2、分别验证S2.loc[1]、S2[1]、S2.iloc[1],并附截图,说明序列变量.loc[i]、序列变量.iloc和序列变量[i]的作用

loc[i]指的是选取列表中标签(索引)为i的数据,而[:]的作用为左闭右闭的选取,而“,”的作用在于是行索引还是列索引

iloc[i]是通过位置去选取数据的,左闭右开,如iloc[1]会返回 Series 中位置为1的值

[i]默认情况下按位置,索引为标签时按标签访问


3、验证以下代码,并结果附截图
 

import pandas as pd
#以列表的形式传入数据

A=[1,3,6,4,9,10,15]
weight=[67,66,83,68,79,88]
sex=['女','男','男','女','男', '男']

B=pd.concat([S2,S3],axis=0)#一般来说,axis=0都是指行,但是在缺失值处理时指的是列
print(B)

S=pd.concat([S2,S3],axis=1)#按列合并序列,合并后为两列成为数据框
print(S)
print(S.loc[0])#第1行
print(S.iloc[0,:])#第1行
print(S[1])#第2列
print(S.iloc[:,1])#第2列
print(S.iloc[1,0])#第二行,第一列
print(S.loc[1,0])
print(S[0:3])#0,1,2行
print(S.iloc[1:3,0:1])#第1,2行,第0列

X=[1,3,6,4,9,8,6]
X=pd.DataFrame(X)#由列表创建数据框,dataframe有idex,value,columns
print(X)
print(X.loc[1])#默认索引为0,1,2,3,4,由索引号(下标)引用元素
print(X[0])
print(X.iloc[1,0])

4、验证以下代码,并将结果附截图,需要在每行备注上用法,并说明如何让sort_index()生效。


import pandas as pd

#3*7二维数组,有几个元素就有几行
weight=[[88,77,67,66,83,68,79],[880,770,670,660,830,680,790],[8,7,6,6,8,6,7]]

#dataframe框架,加入数据,列名,行索引标签abc
df=pd.DataFrame(weight,columns=['num1','num2','num3','num4','num5','num6','num7'],index=['A','C','B'])

print(df)
print(df.loc['A'])#用索引引用标签为A的数据
print(df.loc[['A','C'],:])#获取索引为 'A' 和 'C' 的行,并且包括所有列
print(df.loc['A':'B','num1':'num7'])#从行 'A' 到 'B' 选择,并选择从 'num1' 到 'num7' 的列(包含所有列)
print("-------")
print(df.iloc[0,:])#位置索引,索引位置为“0”的数据
print(df.iloc[[0,2],:])#位置索引,索引位置为“0”-“1”行,所有列的数据
print(df.iloc[:,0:6])#位置索引,索引所有行,“0”-“5”列的数据
df['weight2']=df['num1']*2#新增一列 weight2,其值为 num1 列的每个值乘以 2
print(df['weight2'])
print(df.iloc[:,1])#所有行,位置为“1”的列

df.sort_index()#按索引index排序
print("-----sort_index without inplace-----")#输出没有修改索引排序的数据
print(df)

df.sort_values(by='weight2',inplace=True)#按weight排序,inplace=True很关键
print("----sort_values------")
print(df)

del df['weight2']#删除'weight2'这一列
print("-----del-----")
print(df)

思考1:什么时候需要:inplace=True

何时使用 inplace=True

你通常需要在以下几种情况中使用 inplace=True

  1. 节省内存:
    如果你希望修改原始数据框而不需要返回一个新的副本,可以使用 inplace=True 来节省内存。对于大型数据集,避免创建不必要的副本可以提高性能。

  2. 直接修改数据框:
    当你不需要原始数据框,而是希望直接修改它时,使用 inplace=True 是一个简便的选择。这样你可以直接在原数据框上进行更改,而不必通过赋值操作来创建新的数据框。

  3. 避免重复赋值:
    如果你不想将修改后的结果赋值给一个新变量或原变量,那么使用 inplace=True 会使得操作更简洁。

常见的使用 inplace=True 的场景

  1. 删除列或行:

    df.drop(columns=['num1'], inplace=True)

    这将删除 df 中的 num1 列,而不会返回新的数据框。

  2. 排序数据框:

    df.sort_values(by='num1', inplace=True)

    这将按 num1 列排序数据框,并直接修改 df

  3. 重置索引:

    df.reset_index(drop=True, inplace=True)

    这将重置索引,并且删除原来的索引列(通过 drop=True),直接修改 df

  4. 替换缺失值(NaN):

    df.fillna(0, inplace=True)

    这将用 0 填充 df 中的缺失值,操作会修改原始数据框。

不使用 inplace=True 时的行为:

当你不使用 inplace=True,函数通常会返回一个新的数据框,你需要将其赋值给原变量或另一个变量:

df = df.sort_values(by='num1')

在这种情况下,df 会被修改,并赋值为排序后的数据框。

总结:

  • 使用 inplace=True 可以直接修改原始数据框,避免生成新的副本,节省内存。
  • 不使用 inplace=True 会返回一个新的数据框,适用于你需要保留原始数据框的情况。

你可以根据需求选择是否使用 inplace=True,但要注意,使用 inplace=True 会直接修改原始数据,因此确保你不会丢失重要的数据。如果需要保留原数据框,最好不要使用 inplace=True

思考2:删除操作的drop和del有什么差别

在 Python 中,dropdel 都可以用来删除对象或数据结构中的元素,但它们有一些关键的区别,尤其是在与 Pandas 数据框(DataFrame)打交道时。

1. drop 操作

drop 是 Pandas 中专门用于删除行或列的方法。

用法:
  • 删除行或列时,drop 返回一个新的数据框,并不会修改原始数据框,除非你指定 inplace=True
  • 它适用于删除行或列,并且支持更复杂的操作(例如按标签删除,支持多个列或行的删除等)。
示例:

import pandas as pd # 创建数据框 df = pd.DataFrame({'A': [1, 2, 3], 'B': [4, 5, 6], 'C': [7, 8, 9]}) # 删除一列 df2 = df.drop('B', axis=1) # 删除列 'B' # 删除一行 df3 = df.drop(0, axis=0) # 删除第一行 print(df2) print(df3)

  • axis=1 表示删除列,axis=0 表示删除行。
  • 如果要修改原数据框,可以使用 inplace=True:

  • df.drop('B', axis=1, inplace=True)
特点:
  • drop 支持删除多个行或列。
  • 可以选择删除行或列,灵活性较强。
  • 默认不会修改原数据框,除非使用 inplace=True

2. del 操作

del 是 Python 的内置语句,用于从命名空间中删除对象。在 Pandas 中,它通常用于删除列或行,但它的应用范围不仅限于 Pandas,适用于所有 Python 数据类型。

用法:
  • del 用于删除 Python 变量或对象。
  • 当用于删除 Pandas 数据框的列时,它会直接修改原数据框,而不会返回新的数据框。
  • del 不能删除行,它只能删除列(因为数据框的列是 Pandas 数据框的属性)。
示例:

import pandas as pd # 创建数据框 df = pd.DataFrame({'A': [1, 2, 3], 'B': [4, 5, 6], 'C': [7, 8, 9]}) # 删除一列 del df['B'] # 直接删除列 'B' print(df)

特点:
  • del 会直接修改原数据框,并且不能用来删除行。
  • 删除列时,del 是直接操作,而不像 drop 那样返回一个新的数据框。
  • del 删除的是数据框的列,无法像 drop 一样按标签删除行。

总结

特点dropdel
适用范围删除行或列仅用于删除列
是否返回新对象默认返回新对象,inplace=True 才直接修改原数据框直接修改原数据框,不返回新对象
能否删除行可以(使用 axis=0不行,不能删除行
操作灵活性支持删除多个行或列,可以选择轴 axis只能删除单列
是否修改原数据框不修改原数据框,除非 inplace=True修改原数据框
  • 如果你希望灵活地删除行或列,并且控制是否修改原数据框,drop 是更常用的选择。
  • 如果只是单纯删除列并且不需要返回新数据框,del 可以简洁地完成任务。

5、验证以下代码,并将结果附截图

import pandas as pd

datacsv=pd.read_csv("Bsdata.csv")

# Bsdata.csv文件是研究生开课信息调查表从2600名学生按2%抽样52名调查情况

#r表示当前路径,文件可以从超星下载

print(datacsv.head())

#用pandas读取csv文件实例

datacsv.info()#输出结构信息

h=list(datacsv.身高)

print(h)

print(datacsv.身高.max())

print(datacsv.身高.min())

print(datacsv.loc[1])

print(datacsv.iloc[1,0])

print(datacsv.iloc[1:3,2:3])

#(4)数据框维度

print(datacsv.shape)             #显示数据框的行数和列数

print(datacsv.shape[0])          #数据框行数

print(datacsv.shape[1])          #数据框列数

import pandas as pd

#pd.read_csv() 是 Pandas 中用来读取 CSV 文件的函数。它将 CSV 文件加载到一个 Pandas DataFrame
# Bsdata.csv文件是研究生开课信息调查表从2600名学生按2%抽样52名调查情况
datacsv=pd.read_csv("Bsdata.csv")

#datacsv.head() 返回 DataFrame 的前 5 行(默认情况下)
#用pandas读取csv文件实例
print(datacsv.head())

#datacsv.info() 输出数据集的基本信息,如:数据框的行数和列数,每列的数据类型,每列的非空值数量。
datacsv.info()

#使用 list() 将这一列转换为 Python 的列表(list 类型),并赋值给变量 h
h=list(datacsv.身高)
print(h)
print(datacsv.身高.max())
print(datacsv.身高.min())
print(datacsv.loc[1])
print(datacsv.iloc[1,0])
#第二和第三行的第三列数据
print(datacsv.iloc[1:3,2:3])

#(4)数据框维度
print(datacsv.shape)             #显示数据框的行数和列数
print(datacsv.shape[0])          #数据框行数
print(datacsv.shape[1])          #数据框列数

6、验证以下代码,并将结果附截图,销售流水记录tmp.csv文件可在超星上下载。

import pandas as pd

datacsv=pd.read_csv('销售流水记录tmp.csv',index_col=2,usecols=['create_dt','order_id','sku_id','sku_name','sku_prc','sku_sale_prc','sku_cost_prc'])

print(len(datacsv))

datacsv.info()

datacsv.head()

datacsv['sku_sale_prc']=datacsv['sku_sale_prc'].astype(float)

datacsv.reset_index()

datacsv[['create_dt','sku_sale_prc']].groupby('create_dt').agg(sum)

import pandas as pd

#pandas.read_csv来读取CSV文件,指定了:
#index_col=2:将CSV文件的第三列(order_id)作为行索引。
#usecols:只选择指定的几列进行读取,避免加载不必要的列。
datacsv=pd.read_csv('销售流水记录1.csv',index_col=2,usecols=['create_dt','order_id','sku_id','sku_name','sku_prc','sku_sale_prc','sku_cost_prc'])

#len(datacsv):输出数据集的行数。
#datacsv.info():输出数据集的基本信息,如列名、数据类型和缺失值情况。
#datacsv.head():显示数据的前五行。
print(len(datacsv))
datacsv.info()
datacsv.head()

#将sku_sale_prc列的值转换为浮动类型
datacsv['sku_sale_prc']=datacsv['sku_sale_prc'].astype(float)

#将原来的索引(即order_id)重置为默认的整数索引。如果你不打算保存旧的索引,这行代码可以忽略inplace=True
datacsv.reset_index()

#选取了create_dt和sku_sale_prc两列,然后按create_dt(日期)进行分组,并对sku_sale_prc进行求和。agg(sum)指定了对每个组应用求和操作
datacsv[['create_dt','sku_sale_prc']].groupby('create_dt').agg(sum)

7、验证以下代码,并将结果附截图。

datacsv = pd.read_csv(r'销售流水记录tmp.csv', index_col=[0,1],low_memory=False,encoding='gb18030')#读取指定列,1,2列为索引

datacsv.info()

#pd.read_csv 来读取 CSV 文件,并指定了以下几个参数:
#index_col=[0,1]:表示将文件中的第 0 列和第 1 列作为索引。
#low_memory=False:避免内存优化,在处理大文件时能够提高处理准确性。
#encoding='gb18030':指定文件的编码格式为 gb18030,适合读取包含中文字符的文件。
datacsv = pd.read_csv(r'销售流水记录2.csv', index_col=[0,1],low_memory=False,encoding='gb18030')#读取指定列,1,2列为索引

# datacsv.info() 将返回一个关于数据框(DataFrame)的总结信息,包括:
# 数据框的类型:例如 pandas.DataFrame。
# 行数:即数据框的总行数。
# 列数:数据框中所有列的数量。
# 每列的数据类型:每列的数据类型(例如 int64, float64, object 等)。
# 缺失值:每列中非空(非NaN)值的数量。
datacsv.info()

8、验证以下代码,并将结果附截图。

datacsv = pd.read_csv(r'销售流水记录tmp.csv', usecols=["create_dt","order_id","sku_id","sku_name"], nrows=10)

datacsv.info()

datacsv.head(2)

datacsv.sku_name

# usecols=["create_dt","order_id","sku_id","sku_name"]: 这表示只读取 CSV 文件中的这四列:create_dt, order_id, sku_id 和 sku_name。
# nrows=10: 这会读取文件的前 10 行数据
datacsv = pd.read_csv(r'销售流水记录2.csv', usecols=["create_dt","order_id","sku_id","sku_name"], nrows=10,encoding='gb18030')

# datacsv.info():返回 DataFrame 的摘要信息,包括数据框的大小、列的类型、每列的非空值数量等。
# datacsv.head(2):返回 datacsv 数据框中的前两行数据。
# datacsv.sku_name:返回 datacsv 数据框中名为 sku_name 的列
datacsv.info()
datacsv.head(2)
datacsv.sku_name

9、验证以下代码,并将结果附截图,people.csv可在超星上下载。

import pandas as pd

datacsv=pd.read_csv(r'people.csv',names=["年度","Z","Z0_14","Z15_64","Z65_"],header=None,skiprows=1,index_col=0)#指定列标题

#"年度","Z","Z0_14","Z15_64","Z65_"为列标题,skiprows表示跳过第1行,index_col=0年度(第1列)作为时间序列索引,绘图作为x周

print(datacsv)

datacsv.columns.tolist()

import pandas as pd 

#header=None:告诉 Pandas 数据文件本身没有列标题行,而是通过 names 参数手动设置列名
#skiprows=1:跳过 CSV 文件中的第一行,这通常用于跳过文件中的非数据行
#index_col=0:将 CSV 文件中的第一列(即 "年度" 列)设置为数据的行索引,这样就将年度作为时间序列的索引
datacsv=pd.read_csv(r'people.csv',names=["年度","Z","Z0_14","Z15_64","Z65_"],header=None,skiprows=1,index_col=0)#指定列标题
#"年度","Z","Z0_14","Z15_64","Z65_"为列标题,skiprows表示跳过第1行,index_col=0年度(第1列)作为时间序列索引,绘图作为x周

print(datacsv)
#datacsv.columns 返回一个列索引对象,其中包含数据框的所有列名称。
#tolist() 将列索引转换为 Python 列表形式
datacsv.columns.tolist()

10、利用people.csv文件验证以下代码,并将结果附截图

print(datacsv[datacsv['年度']>'2008'])#提取年度大于2008年的数据

print(datacsv[(datacsv['年度']>'2008')&(datacsv['年度']<'2018')])

#逻辑运算符与、或用&、|表示

import pandas as pd 

#header=None:告诉 Pandas 数据文件本身没有列标题行,而是通过 names 参数手动设置列名
#skiprows=1:跳过 CSV 文件中的第一行,这通常用于跳过文件中的非数据行
#index_col=0:将 CSV 文件中的第一列(即 "年度" 列)设置为数据的行索引,这样就将年度作为时间序列的索引,但是这里'年度' 被设置为索引了,而不是列。所以你不能像普通列那样直接访问它
#如:使用 .index 来访问并进行筛选
#print(datacsv[datacsv.index > 2008])  # 使用索引进行比较
#print(datacsv[(datacsv.index > 2008) & (datacsv.index < 2018)])
#或者删除index_col=0

datacsv=pd.read_csv(r'people.csv',names=["年度" ,"Z","Z0_14","Z15_64","Z65_"],header=None,skiprows=1)
#指定列标题
#"年度","Z","Z0_14","Z15_64","Z65_"为列标题,skiprows表示跳过第1行,index_col=0年度(第1列)作为时间序列索引,绘图作为x周

print(datacsv[datacsv['年度']>'2008'])#提取年度大于2008年的数据
print(datacsv[(datacsv['年度']>'2008')&(datacsv['年度']<'2018')])

6.2.2 pandas工具包绘图

pandas包学习网址Chart visualization — pandas 2.2.3 documentation 

1、读取people.csv文件,指定列标题为"年度","Z","Z0_14","Z15_64","Z65_",利用pandas绘制年度与年末总人口折线图,并附截图,参考代码如下:

import pandas as pd 
import numpy as np
import matplotlib.pyplot as plt

datacsv=pd.read_csv('people.csv',names=["年度","Z","Z0_14","Z15_64","Z65_"],header=None,skiprows=1,index_col=0)
plt.rcParams['font.family']=['STSong']
plt.rcParams['font.size']=16
plt.rcParams['axes.unicode_minus']=False
datacsv['Z'].plot(xlabel='年度',ylabel='年末总人口(万人)',figsize=(10,6),alpha=0.5)

2、利用pandas绘制年度与年末总人口、0-14岁人口折线图,并附截图,参考代码如下:

import pandas as pd 
import numpy as np
import matplotlib.pyplot as plt

datacsv=pd.read_csv('people.csv',names=["年度","Z","Z0_14","Z15_64","Z65_"],header=None,skiprows=1,index_col=0)
plt.rcParams['font.family']=['STSong']
plt.rcParams['font.size']=16
plt.rcParams['axes.unicode_minus']=False
datacsv[['Z','Z0_14']].plot(xlabel='年度',ylabel='年末总人口(万人)',figsize=(10,6))

3、利用pandas绘制年度与各年龄阶段人口变化折线对比图,并附截图,参考代码如下:

import pandas as pd 
import numpy as np
import matplotlib.pyplot as plt

datacsv=pd.read_csv('people.csv',names=["年度","Z","Z0_14","Z15_64","Z65_"],header=None,skiprows=1,index_col=0)
plt.rcParams['font.family']=['STSong']
plt.rcParams['font.size']=16
plt.rcParams['axes.unicode_minus']=False
datacsv.plot(xlabel='年度',ylabel='年末总人口(万人)',figsize=(10,6))

4、利用pandas绘制年度与各年龄阶段人口变化对比复式柱状图,并附截图,参考代码如下:

import pandas as pd 
import numpy as np
import matplotlib.pyplot as plt

datacsv=pd.read_csv('people.csv',names=["年度","Z","Z0_14","Z15_64","Z65_"],header=None,skiprows=1,index_col=0)
plt.rcParams['font.family']=['STSong']
plt.rcParams['font.size']=16
plt.rcParams['axes.unicode_minus']=False
datacsv.plot(kind='bar',xlabel='年度',ylabel='年末总人口(万人)',figsize=(15,6))

5、提取csv文件Bsdata.csv中的身高和体重,利用DataFrame.plot绘制折线图和散点图。

import matplotlib.pyplot as plt

import pandas as pd

plt.style.use('seaborn')

plt.rcParams["font.sans-serif"]=['SimHei']#设置字体,防止中文乱码

plt.rcParams["axes.unicode_minus"]=False  #防止负号乱码

# 引入matplotlib字体管理 FontProperties

# from matplotlib.font_manager import FontProperties

# 设置我们需要用到的中文字体(字体文件地址)

# my_font = FontProperties(fname=r"c:\windows\fonts\SimHei.ttf", size=12)

datacsv=pd.read_csv("Bsdata.csv")

plt.rcParams['font.sans-serif'] = ['SimHei']

datacsv["身高"].plot()#折线图

datacsv["体重"].plot(color="r")#折线图

plt.rcParams['font.sans-serif'] = ['SimHei']

datacsv.plot.scatter(x='身高',y="体重",color="r")#散点图

#提取csv文件Bsdata.csv中的体重,利用DataFrame.plot绘制直方图。

plt.rcParams['font.sans-serif'] = ['SimHei']

datacsv["体重"].hist(color="r")

#提取csv文件Bsdata.csv的开设情况,利用DataFrame.plot绘制开设统计分类柱状图。

# T=datacsv.开设.value_counts()#针对分类数据或定性数据统计

# T.plot(kind='bar')

import matplotlib.pyplot as plt
import pandas as pd
plt.style.use('seaborn')
plt.rcParams["font.sans-serif"]=['SimHei']#设置字体,防止中文乱码
plt.rcParams["axes.unicode_minus"]=False  #防止负号乱码
# 引入matplotlib字体管理 FontProperties
# from matplotlib.font_manager import FontProperties
 
# 设置我们需要用到的中文字体(字体文件地址)
# my_font = FontProperties(fname=r"c:\windows\fonts\SimHei.ttf", size=12)
datacsv=pd.read_csv("Bsdata.csv")
plt.rcParams['font.sans-serif'] = ['SimHei']
datacsv["身高"].plot()#折线图
datacsv["体重"].plot(color="r")#折线图
plt.rcParams['font.sans-serif'] = ['SimHei']
datacsv.plot.scatter(x='身高',y="体重",color="r")#散点图
#提取csv文件Bsdata.csv中的体重,利用DataFrame.plot绘制直方图。
plt.rcParams['font.sans-serif'] = ['SimHei']
datacsv["体重"].hist(color="r")
#提取csv文件Bsdata.csv的开设情况,利用DataFrame.plot绘制开设统计分类柱状图。
# T=datacsv.开设.value_counts()#针对分类数据或定性数据统计
# T.plot(kind='bar')

7.3. 作业

   实验的每一步都需要截图,养成良好的习惯,也是给自己做了一份很好的笔记。

数据源:数据1.csv和数据2.csv

  1. 读取无人售货机数据

在商场不同地点安放了5台自动售货机,编号分别为A、B、C、D、E。数据1提供了从2017年1月1日至2017年12月31日每台自动售货机的商品销售数据,数据2提供了商品的分类。现在要对两个表格中的数据进行合并。

  1. 使用pandas中的read_csv函数分别读取数据。
  2. 使用pandas中的merge函数或者join方法进行数据合并
  3. 保存合并后的结果
# (1)使用pandas中的read_csv函数分别读取数据。
# (2)使用pandas中的merge函数或者join方法进行数据合并
# (3)保存合并后的结果

import pandas as pd
import warnings

warnings.filterwarnings('ignore')
sale=pd.read_csv('数据1.csv',encoding='gb18030')
categlories=pd.read_csv('数据2.csv',encoding='gb18030')

merged=pd.merge(sale,categlories,on="商品",how='inner')

merged.to_csv('12data_inner_merged.csv',encoding='gb18030')

2.对1中合并的数据进行数据校验、清洗,如重复值校验与处理、异常值校验与处理、缺失值校验与处理。对每一步的操作都做出说明分析。

  1. 查找重复记录并进行删除
  2. 查找异常数据,并在箱线图中绘制处理,最后对异常数据进行删除
  3. 查找缺失值并进行处理(删除、填充等)。
  4. 保存处理后的数据
import pandas as pd
import matplotlib.pyplot as plt

# 设置中文字体
plt.rcParams['font.sans-serif'] = ['SimHei']  # 设置字体为黑体
plt.rcParams['axes.unicode_minus'] = False  # 解决负号显示问题

# 1. 读取CSV文件,指定编码
def load_data(file_path):
    """加载数据并指定编码"""
    df = pd.read_csv(file_path, encoding='gb18030')
    return df

# 2. 查找并删除重复记录
def remove_duplicates(df):
    """查找并删除重复记录"""
    duplicate_count = df.duplicated().sum()
    print(f"重复记录的数量: {duplicate_count}")
    
    # 删除重复记录
    df = df.drop_duplicates()
    return df

# 3. 查找并处理异常值(箱线图与IQR法)
def remove_outliers(df, columns):
    """查找并删除异常值"""
    for column in columns:
        if column in df.columns:
            # 确保该列是数字类型,强制转换为数字
            df[column] = pd.to_numeric(df[column], errors='coerce')
            
            # 如果列中有 NaN 值,填充为该列的均值(或者其他适合的填充值)
            df[column].fillna(df[column].mean(), inplace=True)

            # 绘制箱线图
            plt.figure(figsize=(8, 6))
            df[column].plot(kind='box', vert=False, patch_artist=True)
            plt.title(f'箱线图 - {column}')
            plt.show()

            # 使用 IQR 法查找异常值
            Q1 = df[column].quantile(0.25)
            Q3 = df[column].quantile(0.75)
            IQR = Q3 - Q1
            lower_bound = Q1 - 1.5 * IQR
            upper_bound = Q3 + 1.5 * IQR
            
            # 统计异常值的数量
            outliers = df[(df[column] < lower_bound) | (df[column] > upper_bound)]
            print(f"列 '{column}' 中的异常值数量: {outliers.shape[0]}")
            
            # 删除异常值
            df = df[(df[column] >= lower_bound) & (df[column] <= upper_bound)]
    return df

# 4. 查找并处理缺失值(删除或填充)
def handle_missing_values(df, columns, fill_value=None):
    """查找并处理缺失值"""
    for column in columns:
        if column in df.columns:
            missing_count = df[column].isnull().sum()
            print(f"列 {column} 中的缺失值数量: {missing_count}")

            if missing_count > 0:
                if fill_value is not None:
                    # 填充缺失值(用给定的值填充)
                    df[column].fillna(fill_value, inplace=True)
                    print(f"列 {column} 的缺失值已用 {fill_value} 填充")
                else:
                    # 删除缺失值
                    df = df.dropna(subset=[column])
                    print(f"列 {column} 的缺失值已删除")
    return df

# 5. 清洗数据的主函数
def clean_data(file_path, fill_missing_value=None):
    """加载并清洗数据"""
    # 读取数据
    df = load_data("12data_inner_merged.csv")
    
    # 处理重复记录
    df = remove_duplicates(df)
    
    # 处理异常值(根据IQR法)
    df = remove_outliers(df, ['应付金额', '实际金额'])
    
    # 处理缺失值
    df = handle_missing_values(df, ['应付金额', '实际金额'], fill_missing_value)
    
    # 保存处理后的数据
    output_file = 'cleaned_data.csv'
    df.to_csv(output_file, encoding='gb18030', index=False)
    print(f"清洗后的数据已保存到: {output_file}")
    
    return df
    # 示例:使用上面的函数来清洗数据

cleaned_data = clean_data(file_path, fill_missing_value=0)  # 例如用0填充缺失值



3.针对数据1

  1. 绘制出每个月的订单量的柱状图,用pandas进行绘图展示(要求添加标题、X轴和Y轴名称)
  2. 绘制出每个月的销售额变化情况折线图,用pandas进行绘图展示(要求添加标题、X轴和Y轴名称)
  3. 绘制出A类自动售货机中商品名称为”怡宝纯净水”的商品,12个月中每个月的订单量饼图,用pandas进行绘图展示(要求添加标题、饼图按照订单量进行排序展示)

     4.对五类自动售货机的实付金额数据,分别绘制出箱线图。

# (1)绘制出每个月的订单量的柱状图,用pandas进行绘图展示(要求添加标题、X轴和Y轴名称)
# (2)绘制出每个月的销售额变化情况折线图,用pandas进行绘图展示(要求添加标题、X轴和Y轴名称)
# (3)绘制出A类自动售货机中商品名称为”怡宝纯净水”的商品,12个月中每个月的订单量饼图,用pandas进行绘图展示(要求添加标题、饼图按照订单量进行排序展示)
# (4)对五类自动售货机的实付金额数据,分别绘制出箱线图。

import pandas as pd
import matplotlib.pyplot as plt

plt.rcParams['font.sans-serif'] = ['SimHei']  # 设置字体为黑体
plt.rcParams['axes.unicode_minus'] = False  # 解决负号显示问题

# 假设 df 是你的订单数据 DataFrame
# 示例数据加载
# 使用此行代码加载数据文件(假设是CSV文件)
df = pd.read_csv('数据1.csv', encoding='gb18030')

# 确保订单日期是 datetime 类型
df['订单日期'] = pd.to_datetime(df['支付时间'], errors='coerce')

# 删除无效日期
df = df.dropna(subset=['订单日期'])

# 提取月份,转换为字符串类型
df['月份'] = df['订单日期'].dt.to_period('M').astype(str)

# 确保 '实际金额' 列是数值类型,非数值的会变为 NaN
df['实际金额'] = pd.to_numeric(df['实际金额'], errors='coerce')

# 删除 '实际金额' 列中的 NaN 值
df = df.dropna(subset=['实际金额'])


#(1)绘制每个月的订单量柱状图
monthly_orders = df.groupby('月份')['商品'].count()

plt.figure(figsize=(10, 6))
monthly_orders.plot(kind='bar', color='skyblue')
plt.title('每个月的订单量')
plt.xlabel('月份')
plt.ylabel('订单量')
plt.xticks(rotation=45)
plt.show()

#(2)绘制每个月的销售额变化情况折线图
monthly_sales = df.groupby('月份')['实际金额'].sum()

plt.figure(figsize=(10, 6))
monthly_sales.plot(kind='line', color='green', marker='o')
plt.title('每个月的销售额变化情况')
plt.xlabel('月份')
plt.ylabel('销售额')
plt.xticks(rotation=45)
plt.grid(True)
plt.tight_layout()
plt.show()

#(3)绘制A类自动售货机中商品名称为"怡宝纯净水"的商品,12个月中每个月的订单量饼图
df_filtered = df[(df['地点'] == 'A') & (df['商品'] == '怡宝纯净水')]
monthly_order_quantity = df_filtered.groupby('月份')['实际金额'].sum()

# 按订单量排序
monthly_order_quantity_sorted = monthly_order_quantity.sort_index()  # 按月份排序

plt.figure(figsize=(10, 10))
monthly_order_quantity_sorted.plot(kind='pie', autopct='%1.1f%%', startangle=90)
plt.title('怡宝纯净水每个月的订单量')
plt.ylabel('')  # 去掉y轴标签
plt.show()

#(4)绘制五类自动售货机的实付金额箱线图
fig, ax = plt.subplots(figsize=(15, 9))

# 绘制箱线图
df.boxplot(column='实际金额', by='地点', patch_artist=True, ax=ax)

# 添加标题和标签
ax.set_title('五类自动售货机的实付金额分布')
ax.set_xlabel('地点')
ax.set_ylabel('实际金额')

# 去掉默认的标题
plt.suptitle('')

# 显示图形
plt.show()

感兴趣的可以私聊我拿数据练练手。

### Python 机器学习中的数据可视化 #### 使用 Matplotlib 和 Seaborn 进行基础绘图 Matplotlib 是一个广泛使用的 Python 绘图,Seaborn 则是在其基础上构建的一个高级接口,特别适合用于统计图形绘制。两者都支持丰富的图表类型,可以满足大多数的数据探索需求。 ```python import matplotlib.pyplot as plt import seaborn as sns tips = sns.load_dataset('tips') sns.set_theme(style="whitegrid") # 创建箱形图来展示不同时间段的小费分布情况 ax = sns.boxplot(x="day", y="total_bill", data=tips) plt.title('Total Bill by Day of Week', fontsize=16) plt.show() ``` 此代码片段展示了如何加载内置数据集并创建一个简单的箱型图以比较一周内每天总账单金额的变化趋势[^1]。 #### Pandas 的 Plot 方法简化绘图过程 Pandas 提供了一个便捷的方法 `.plot()` ,可以直接调用来快速生成常见的图表样式,比如折线图、柱状图等。这对于初步了解数据的整体结构非常有用。 ```python import pandas as pd df = pd.DataFrame({ 'A': ['foo', 'bar', 'foo', 'bar'], 'B': range(4), }) grouped = df.groupby('A').sum() # 直接通过 DataFrame 对象调用 plot 函数画出条形图 grouped.plot(kind='bar') plt.ylabel('Sum of B') plt.xlabel('Category A') plt.title('Bar Chart Example Using Pandas Built-in Functionality') plt.show() ``` 这段脚本说明了怎样利用 `pandas` 中的分组聚合操作以及自带的绘图方法制作直观易懂的条形图[^2]。 #### Scikit-Learn 配合 Yellowbrick 实现模型评估可视化 Yellowbrick 是专门为 scikit-learn 设计的一套扩展工具包,旨在帮助开发者更好地理解他们的建模流程。其中包含了大量针对监督学习任务(如分类器性能评价)而设计的独特视图组件。 ```python from yellowbrick.classifier import ClassificationReport, ConfusionMatrix from sklearn.datasets import load_iris from sklearn.model_selection import train_test_split from sklearn.svm import SVC data = load_iris() X_train, X_test, y_train, y_test = train_test_split(data.data, data.target, test_size=.2) model = SVC().fit(X_train, y_train) visualizer = ClassificationReport(model, classes=data.target_names) visualizer.fit(X_train, y_train) # Fit the training data to visualizer visualizer.score(X_test, y_test) # Evaluate with testing set g = visualizer.poof() # Draw/show/poof the data ``` 上述例子介绍了如何借助 Yellowbrick 内的 `ClassificationReport` 类生成一份详细的分类报告矩阵,并将其应用于实际案例之中[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值