数学建模导论 --- pandas的简单使用
数学建模导论 --- pandas的简单使用
--2025年2月学习笔记
学习内容摘自intro-mathmodel-课程详情 | Datawhale
感谢分享!
学习数学建模更重要的是知道面对不同体量的数据如何快速下手找准最合适的建模方法
靠山吃山,靠水吃水。小数据有小数据的方法,大数据有大数据的方法。拿着线性回归的那一套去拟合大数据,往往效果不会很好;拿着神经网络去学小数据,学到的东西往往没有意义(我们会笑称:你是想去研究few-shot learning吗)。面对不同的数据,能够使用最合适的方法最为重要。而判断此方法是否合适,一个根本的衡量就是数据的体量。
数据科学的研究对象
- 数据的获取和存储:包括爬虫、软件定义存储、硬件存储有关背景知识等。
- 数据的处理:包括分布式计算、并行计算、数据流等知识,以及Hadoop、Spark等大数据框架。
- 数据的分析:包括统计学、数据挖掘与机器学习、计算机视觉、自然语言处理等内容,重在挖掘数据中的模式与知识。
- 数据的管理:现代数据库系统及其架构等内容。
- 数据的应用:数据可视化、数据相关软件的开发、报表分析以及如何将数据挖掘得到的结果还原为实际问题的解决方案。
使用pandas处理数据的基础
1.环境相关
这里我使用的是pycharm进行的python编写,环境是用conda建的新环境
python = 3.10
# 使用清华镜像源下载更快
pip insatll pandas -i https://pypi.tuna.tsinghua,edu.cn/simple
2.练习一
import pandas as pd
import numpy as np
# 字典格式
data = {'animal': ['cat', 'cat', 'snake', 'dog', 'dog', 'cat', 'snake', 'cat', 'dog', 'dog'],
'age': [2.5, 3, 0.5, np.nan, 5, 2, 4.5, np.nan, 7, 3],
'visits': [1, 3, 2, 3, 2, 3, 1, 1, 2, 1],
'priority': ['yes', 'yes', 'no', 'yes', 'no', 'no', 'no', 'yes', 'no', 'no']}
# 作为索引
labels = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']
df = pd.DataFrame(data)
# 默认输出有数值的统计结果
print(df.describe())
# age visits
# count 8.000000 10.000000
# mean 3.437500 1.900000
# std 2.007797 0.875595
# min 0.500000 1.000000
# 25% 2.375000 1.000000
# 50% 3.000000 2.000000
# 75% 4.625000 2.750000
# max 7.000000 3.000000
# 计数,均值,标准差,最小值。。。。最大值
# 增加参数即可输出上面的animal和priority
print(df.describe(include='all'))
# animal age visits priority
# count 10 8.000000 10.000000 10
# unique 3 NaN NaN 2
# top cat NaN NaN no
# freq 4 NaN NaN 6
# mean NaN 3.437500 1.900000 NaN
# std NaN 2.007797 0.875595 NaN
# min NaN 0.500000 1.000000 NaN
# 25% NaN 2.375000 1.000000 NaN
# 50% NaN 3.000000 2.000000 NaN
# 75% NaN 4.625000 2.750000 NaN
# max NaN 7.000000 3.000000 NaN
# 输出为数据的前五列
print(df.head(5))
# animal age visits priority
# 0 cat 2.5 1 yes
# 1 cat 3.0 3 yes
# 2 snake 0.5 2 no
# 3 dog NaN 3 yes
# 4 dog 5.0 2 no
# 除了最后一列不输出
print(df.head(-1))
# animal age visits priority
# 0 cat 2.5 1 yes
# 1 cat 3.0 3 yes
# 2 snake 0.5 2 no
# 3 dog NaN 3 yes
# 4 dog 5.0 2 no
# 5 cat 2.0 3 no
# 6 snake 4.5 1 no
# 7 cat NaN 1 yes
# 8 dog 7.0 2 no
# 打印有动物和age的列
print(df[['animal', 'age']])
# animal age
# 0 cat 2.5
# 1 cat 3.0
# 2 snake 0.5
# 3 dog NaN
# 4 dog 5.0
# 5 cat 2.0
# 6 snake 4.5
# 7 cat NaN
# 8 dog 7.0
# 9 dog 3.0
# 全部打印
print(df)
# animal age visits priority
# 0 cat 2.5 1 yes
# 1 cat 3.0 3 yes
# 2 snake 0.5 2 no
# 3 dog NaN 3 yes
# 4 dog 5.0 2 no
# 5 cat 2.0 3 no
# 6 snake 4.5 1 no
# 7 cat NaN 1 yes
# 8 dog 7.0 2 no
# 9 dog 3.0 1 no
# 输出3 4 8行的 animal age
print(df.loc[[3, 4, 8], ['animal', 'age']])
# animal age
# 3 dog NaN
# 4 dog 5.0
# 8 dog 7.0
# 输出原有index
print(df.index)
# RangeIndex(start=0, stop=10, step=1)
# 更改index
df.index = labels
print(df.index)
# Index(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'], dtype='object')
print('改变之前:', df.loc[['f'],['age']])
df.loc[['f'], ['age']] = 1.5
print('改变之后:', df.loc[['f'],['age']])
# 改变之前: age
# f 2.0
# 改变之后 age
# f 1.5
# 求和
print(df['visits'].sum())
# 19
print(df.groupby(['animal'])['age'].mean())
# animal
# cat 2.333333
# dog 5.000000
# snake 2.500000
# Name: age, dtype: float64
3.练习二
import numpy as np
import pandas as pd
df = pd.DataFrame({'From_To': ['LoNDon_paris', 'MAdrid_miLAN', 'londON_StockhOlm', 'Budapest_PaRis', 'Brussels_londOn'],
'FlightNumber': [10045, np.nan, 10065, np.nan, 10085],
'RecentDelays': [[23, 47], [], [24, 43, 87], [13], [67, 32]],
'Airline': ['KLM(!)', '<Air France> (12)', '(British Airways. )', '12. Air France', '"Swiss Air"']})
# 打印出来看看df
print(df)
# From_To FlightNumber RecentDelays Airline
# 0 LoNDon_paris 10045.0 [23, 47] KLM(!)
# 1 MAdrid_miLAN NaN [] <Air France> (12)
# 2 londON_StockhOlm 10065.0 [24, 43, 87] (British Airways. )
# 3 Budapest_PaRis NaN [13] 12. Air France
# 4 Brussels_londOn 10085.0 [67, 32] "Swiss Air"
# 缺失值常用nan表示
# interpolate() 是 Pandas 中的一个方法,用于填补缺失值(NaN)。
# 它使用插值算法推测缺失数据点的值,默认情况下采用线性插值(通过连接已知点的直线来估算未知点的值)
# astype(int) 方法将插值后的 FlightNumber 列的所有数据转换为整数类型。
df['FlightNumber'] = df['FlightNumber'].interpolate().astype(int)
print(df)
# From_To FlightNumber RecentDelays Airline
# 0 LoNDon_paris 10045 [23, 47] KLM(!)
# 1 MAdrid_miLAN 10055 [] <Air France> (12)
# 2 londON_StockhOlm 10065 [24, 43, 87] (British Airways. )
# 3 Budapest_PaRis 10075 [13] 12. Air France
# 4 Brussels_londOn 10085 [67, 32] "Swiss Air"
temp = df['From_To'].str.split("_", expand=True)
print(temp)
# 0 1
# 0 LoNDon paris
# 1 MAdrid miLAN
# 2 londON StockhOlm
# 3 Budapest PaRis
# 4 Brussels londOn
# 赋予为列From与To
temp.columns = ['From', 'To']
print(temp)
# From To
# 0 LoNDon paris
# 1 MAdrid miLAN
# 2 londON StockhOlm
# 3 Budapest PaRis
# 4 Brussels londOn
# 处理首字母
temp['From'] = temp['From'].str.capitalize()
temp['To'] = temp['To'].str.capitalize()
print(temp)
# From To
# 0 London Paris
# 1 Madrid Milan
# 2 London Stockholm
# 3 Budapest Paris
# 4 Brussels London
# 'From_To':
# 这是你想要删除的列名。在这个例子中,删除的是名为 'From_To' 的列。
# axis 参数指定是删除行还是列:
# axis=0 表示删除行(按行操作)。
# axis=1 表示删除列(按列操作)。
# inplace=True 表示直接在原数据框 df 上进行操作,修改会生效并且不会返回新的数据框。即,不需要重新赋值给 df,它会在原地修改数据框。
# 如果设置为 inplace=False(默认值),则 drop() 方法会返回一个删除指定列的新的数据框,而原数据框 df 不会被改变。
df.drop('From_To', axis=1, inplace=True)
print(df)
# FlightNumber RecentDelays Airline
# 0 10045 [23, 47] KLM(!)
# 1 10055 [] <Air France> (12)
# 2 10065 [24, 43, 87] (British Airways. )
# 3 10075 [13] 12. Air France
# 4 10085 [67, 32] "Swiss Air"
# 合并到df
df[['From', 'To']] = temp
print(df)
# FlightNumber RecentDelays Airline From To
# 0 10045 [23, 47] KLM(!) London Paris
# 1 10055 [] <Air France> (12) Madrid Milan
# 2 10065 [24, 43, 87] (British Airways. ) London Stockholm
# 3 10075 [13] 12. Air France Budapest Paris
# 4 10085 [67, 32] "Swiss Air" Brussels London
# 去除其他字符
# r'([a-zA-Z\s]+)' 是正则表达式,用于匹配字符串中连续的字母和空格
# strip()去除首位空格,但是中间不管
df['Airline'] = df['Airline'].str.extract(r'([a-zA-Z\s]+)', expand=False).str.strip()
print(df)
# FlightNumber RecentDelays Airline From To
# 0 10045 [23, 47] KLM London Paris
# 1 10055 [] Air France Madrid Milan
# 2 10065 [24, 43, 87] British Airways London Stockholm
# 3 10075 [13] Air France Budapest Paris
# 4 10085 [67, 32] Swiss Air Brussels London
delays = df['RecentDelays'].apply(pd.Series)
print(delays)
# 0 1 2
# 0 23.0 47.0 NaN
# 1 NaN NaN NaN
# 2 24.0 43.0 87.0
# 3 13.0 NaN NaN
# 4 67.0 32.0 NaN
delays.columns = ['delay_%s' % i for i in range(1, len(delays.columns)+1)]
df = df.drop('RecentDelays', axis=1).join(delays, how='left')
# join(delays, how='left')的主体似乎是dalays来区分左右
print(df)
# FlightNumber Airline From ... delay_1 delay_2 delay_3
# 0 10045 KLM London ... 23.0 47.0 NaN
# 1 10055 Air France Madrid ... NaN NaN NaN
# 2 10065 British Airways London ... 24.0 43.0 87.0
# 3 10075 Air France Budapest ... 13.0 NaN NaN
# 4 10085 Swiss Air Brussels ... 67.0 32.0 NaN
# 将delay_i列的控制nan都填为自身的平均值。fillna自如其意
for i in range(1, 4):
df[f'delay_{i}'] = df[f'delay_{i}'].fillna(np.mean(df[f'delay_{i}']))
print(df)
# FlightNumber Airline From ... delay_1 delay_2 delay_3
# 0 10045 KLM London ... 23.00 47.000000 87.0
# 1 10055 Air France Madrid ... 31.75 40.666667 87.0
# 2 10065 British Airways London ... 24.00 43.000000 87.0
# 3 10075 Air France Budapest ... 13.00 40.666667 87.0
# 4 10085 Swiss Air Brussels ... 67.00 32.000000 87.0
# 增加一行相同的
df = df._append(df.loc[df['FlightNumber'] == 10085, :], ignore_index=True)
print(df)
# [5 rows x 7 columns]
# FlightNumber Airline From ... delay_1 delay_2 delay_3
# 0 10045 KLM London ... 23.00 47.000000 87.0
# 1 10055 Air France Madrid ... 31.75 40.666667 87.0
# 2 10065 British Airways London ... 24.00 43.000000 87.0
# 3 10075 Air France Budapest ... 13.00 40.666667 87.0
# 4 10085 Swiss Air Brussels ... 67.00 32.000000 87.0
# 5 10085 Swiss Air Brussels ... 67.00 32.000000 87.0
# 去重
df = df.drop_duplicates()
print(df)
# FlightNumber Airline From ... delay_1 delay_2 delay_3
# 0 10045 KLM London ... 23.00 47.000000 87.0
# 1 10055 Air France Madrid ... 31.75 40.666667 87.0
# 2 10065 British Airways London ... 24.00 43.000000 87.0
# 3 10075 Air France Budapest ... 13.00 40.666667 87.0
# 4 10085 Swiss Air Brussels ... 67.00 32.000000 87.0
数据的规约
min-max规约的表达式形如:
这一操作的目的是为了消除量纲影响,所有的属性都被规约到[0,1]的范围内,数据的偏差不会那么大。但是如果出现异常值,比如非常大的数值,那么这个数据的分布是有偏的。为了对数据的分布进行规约,还会使用到另一个常用的方法就是Z-score规约:
本质上,一列数据减去其均值再除以标准差,如果这一列数据近似服从正态分布,这个过程就是化为标准正态分布的过程。Z-score规约和min-max规约往往不是二者取其一,有时候两个可以组合起来用。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· 清华大学推出第四讲使用 DeepSeek + DeepResearch 让科研像聊天一样简单!
· 实操Deepseek接入个人知识库
· 易语言 —— 开山篇
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比