笔记
' 123 '.strip()#去除两端的空格
#123
#在别的文件中使用该py文件中的路径时会发生错误,防止路径错误
DIR=os.path.dirname(os.path.abspath(__file__))#获取当前文件的绝对路径,删除文件的.py文件后缀得到路径
df=pd.read_csv(os.path.join(DIR,'data','data.csv'))#根据py文件定位csv文件位置
for i in df:
print(df[i].value_counts().head(10))
print(df[i].value_counts().tail(10))
contains方法(已用fill代替)
str.contains() 匹配字符串(正则表达式)是否存在于某一数据中 无法对存在空值的列进行查找
s1 = pd.Series(['Mouse', 'dog', 'house and parrot', '23', np.NaN])
s1.str.contains('og', regex=False) #匹配文字是否存在og
0 False
1 True
2 False
3 False
4 NaN
dtype: object
regex正则表达式匹配(默认为True) 是否将要匹配的文字视为正则表达式
# s1.str.contains('\d', regex=True)
r=df['date_week'].str.contains('\d* 星期一', regex=True)#是否存在 正则表达式 对应的文字
df.loc[r,'date_week']
#2022-04-04 星期一
#2022-04-11 星期一
数据清理
查看数据
词频统计能有效的对异常数据进行筛选
for i in df:
print(df[i].value_counts().head(10))
print(df[i].value_counts().tail(10))
print(df.dtypes)#查看每一列数据类型
print(df.isna().sum())#空值数量求和
print(df.describe())#数据统计
'123'.isdigit()#判断字符串是 数字 组成
#True
'ABC'.isupper()#判断字符串是否是 大写字母 组成
#True
'abc'.islower()#判断字符串是否是 小写字母 组成
#True
日期格式处理
-
- %Y 年
-
- %b 月份缩写
-
- %m 月
-
- %d 天
-
- %H 时
-
- %M 分
-
- %S 秒
格式转换
strptime(date_string,date_format) strftime(date_format)
from datetime import datetime
date_string = 'Oct-09' #假定日期格式
date_format = '%b-%d' # %b 表示月份缩写,%d 表示日
date_obj = datetime.strptime(
date_string,#时间字符串
date_format,#日期格式
) #1900-10-01 00:00:00
specific_date = datetime(2022, int(date_obj.month), int(date_obj.day)).strftime('%Y/%m/%d')
#分别获取年月日的数字,进行格式转换得到结果
#'2022/10/09'
#提取月份
#英文缩写月份格式转换
from datetime import datetime
date=datetime.strptime('Dec','%b')
print(date)#1900-12-01 00:00:00
print(date.month)#12
难点
-
- 空字符串
-
- 仅有月日或日
-
- 英文月份缩写
-
- 日期(时区)
-
- 月日缺少0
统一格式 1990/01/01
-
- 使用strip对字符串两端进行去除空格
-
- 对为空字符串的数据不做处理(默认值数据)
-
- 将-替换为/
-
- 对根据(对字符串进行划分,取0索引(去除日期(时区)的情况)
-
- 取前3索引,应为y,m,d
-
- 根据前3列表长度判断,年月日是否有空缺
-
- 对月份是英文缩写的情况单独进行处理,使用datetime.strptime()对月份格式进行处理
-
- 将得到的y,m,d通过datetime.strftime()进行格式转换得到结果
from datetime import datetime
def replace_m(m):
if m.isdigit():#判断是否为数字组成
return m #月份不做处理
else:
return datetime.strptime('Dec','%b').month #日期格式转换,返回month数字
date_list = []
for i in df['date'].str.strip(): #去除两端空格
y = '1990'#默认值ymd
m = '01'
d = '01'
if i == '':#i为空不做处理
continue
else:
date=i.replace('-', '/').split('(')#将-替换为/ 根据(分割
date = date[0] #去掉1995-12-01 (北京)
date = date.split('/') #通过/分割
date_list = date[:3] #只取列表前3位日期,应为Y,M,D
if len(date_list) == 3: #齐全的数据 ['2022','09','02']
y = date_list[0]
m = replace_m(date_list[1]) #需要对月份进行处理,判断是否存在英文缩写
d = date_list[2]
elif len(date_list) == 2: #有月日的数据 ['09','02']
y = '1990'
m = replace_m(date_list[0]) # 长度只有2所以仅有月日 索引0为月
d = date_list[1] # 索引1为日
elif len(date_list) == 1: #只有日的数据
y = '1990'
m = '01'
d = date_list[0] # 索引0为日
d = datetime(int(y), int(m), int(d)).strftime('%Y/%m/%d') #对月日补充0
date_list.append(d) # 1990/01/01
df['date'] = date_list
#encoing:utf-8
from datetime import datetime
# 1995/12/01
# 1995-12-01 12-05 oct-01 2001-oct-01
# 空字符串 只有日 1995-12-01(北京) 1995-12-01-北京
'''
输入的m可能是数字也可能是月份英文缩写,转成数字
'''
def handle_month(m):
# m = m.lower()
mword_dic = {"Jan":1,"Feb":2,"Mar":3,"Apr":4,"May":5,"Jun":6,"Jul":7,"Aug":8,"Sep":9,"Sept":9,"Oct":10,"Nov":11,"Dec":12} #时间关系只写3个
if m in mword_dic: #说明m是英文缩写
return mword_dic[m]
else:
return int(m)
def date_fun(date_str):
date_str =date_str.strip() #去掉前后空格
if date_str=='':
year = 1990
month = 1
d = 1
else:
item = date_str.split("(")
date_str = item[0] # 去掉1995-12-01(北京) 这种情况的时区
date_str = date_str.replace("/","-")
item = date_str.split("-")
item = item[:3] # 去掉1995-12-01-北京 这种情况的时区,这时候item的长度最多是3
if len(item)==3: #包含年
year = int(item[0])
month = handle_month(item[1])
d = int(item[2])
elif len(item)==2: #只有月和日
year = 1990
month = handle_month(item[0])
d = int(item[1])
elif len(item)==1: # 只有日或者空字符串(所有空字符串的情况放在最开始处理)
year = 1990
month = 1
d = int(item[0])
return datetime(year,month,d).strftime("%Y/%m/%d")
#使用try处理日期处理代码
#无法对'Oct-09'这样的数据进行处理
from datetime import datetime
date_list=[]
for i in df['date'].str.replace('-', '/').split('/'):
y = '1990'
m = '01'
d = '01'
try:
if len(i[0]) == 4 and i[0].isdigit():
y = i[0]
except:
pass
try:
if len(i[1]) == 2 and i[1].isdigit():
m = i[1]
except:
pass
try:
if len(i[2]) == 2 and i[2].isdigit():
d = i[2]
except:
pass
d=datetime(int(y),int(m),int(d)).strftime('%Y/%m/%d') # 1990/01/01
date_list.append(d)
df['date']=date_list
电影类型填空
难点
-
- 定位包含指定名字的行
-
- 获取类型列表
-
- 权重累加
流程
-
- 首先先将数据分为电影类型列 有空值(isna)和无空值(notna)的2组数据
-
- 创建存放结果数据的fill_null_vakue_list列表
-
- 遍历每一个电影类型列有空值的行
-
- 对导演、主编、演员(取前三位)使用/划分得到名字列表
-
- 接着根据每一个导演、主编、演员的名字在无空值的数据中寻找他们都参演过什么类型的电影 将参演过的电影类型全部存入列表返回
['恐怖','爱情','校园','科幻','恐怖','恐怖']
- 接着根据每一个导演、主编、演员的名字在无空值的数据中寻找他们都参演过什么类型的电影 将参演过的电影类型全部存入列表返回
#找得到返回索引
#找不到会返回-1
for i in not_na_df[not_na_df['city'].str.find(fill_key) != -1].values:
print(i)
-
- 通过字典统计计算权重分值 遍历 参演过电影类型列表 中的每一个电影类型名称 如果没存在于字典中就添加为1,已存在就对该类型进行累加分值
{'电影类型':'权重分值'}
- 通过字典统计计算权重分值 遍历 参演过电影类型列表 中的每一个电影类型名称 如果没存在于字典中就添加为1,已存在就对该类型进行累加分值
-
- 运行完一行 电影类型有空值 的数据后结果获得
{'恐怖': 3, '爱情': 2, '校园': 1, '科幻': 1}
- 运行完一行 电影类型有空值 的数据后结果获得
import pandas as pd
#创建Series对象后对数据进行排序,取前4个分值最高的数据
data=pd.Series(all_type_dic).sort_values(ascending=False)).head(4)
#字符串拼接/得到结果
result='/'.join(data.index)
#'恐怖/爱情/校园/科幻'
-
- 添加到fill_null_vakue_list列表中
-
- 构建ser数据,保存csv数据
# 电影类型填充
import pandas as pd
df = pd.read_csv('data/movie.csv') # 读取文件
movie_type_null = df.loc[df['movie_type'].isnull()] # 将将电影类型为空和不为空的分别筛选出来
movie_type_no_null = df.loc[df['movie_type'].notnull()] # 将将电影类型为空和不为空的分别筛选出来
def calc_movie_type(field_value, field_name, data):
"""
:param field_value:字段值
:param field_name:字段名
:param data:整体数据表
:return:
"""
field_lst = data.loc[data[field_name].str.contains(field_value), 'movie_type'].values
# 在影片类型不为空的数据中,对导演列数据使用contains(不需要对导演数据拆分也可以找到包含该导演的行)筛选哪些行数据包含了该名导演,定位'movie_type'影片类型列
result_lst = []
for typ in field_lst: # 对包含该导演的影片类型数据行进行处理
result_lst.extend((typ.split('/'))) # 分割字符串 获取影片类型列表
return result_lst
fill_null_vakue_list = [] # 填充空值的列表,存放要电影类型
for row in movie_type_null.values: # 遍历电影类型为空的df
row_director_list = row[1].split('/') # 对导演进行分割
row_editor_list = row[2].split('/') # 主编
row_actor_list = row[3].split('/')[:3] # 演员。只取前三
all_type_dic = {} # set用于去重
# 计算导演类型推断
for director in row_director_list: # 获取每一个导演名,对每这一部电影的导演进行处理
dire_type_list = calc_movie_type(director, 'director', movie_type_no_null) # 返回该导演演过的所有电影的 电影类型列表
# ['恐怖','爱情','校园','科幻','恐怖','恐怖']
for d_t in dire_type_list: # 对该导演演过的所有电影类型数据进行遍历
if d_t not in all_type_dic: # 是否存在于set(数据唯一)中,如果不存在则创建
all_type_dic[d_t] = 0
# all_type_dic[d_t] = dire_type_list.count(d_t*1)
# 得到{'恐怖':0,'爱情':0}
all_type_dic[d_t] += 1
# 得到{'恐怖':1,'爱情':0}
# 计算编剧类型推断
for editor in row_editor_list:
edit_type_list = calc_movie_type(editor, 'editor', movie_type_no_null)
for e_t in edit_type_list:
if e_t not in all_type_dic:
all_type_dic[e_t] = 0
all_type_dic[e_t] += 0.8
# 计算演员类型推断
# 演员的权重会不断衰减
init_weight = 1 # 默认权重
for actor in row_actor_list:
type_list = calc_movie_type(actor, 'actor', data=movie_type_no_null)
for m_t in type_list:
if m_t not in all_type_dic:
all_type_dic[m_t] = 0
# all_type_dic[m_t] = dire_type_list.count(m_t*init_weight)
all_type_dic[m_t] += init_weight # 添加权重
init_weight -= 0.2 # 统计计算完后进行衰减
# 排序
sorted_type = sorted(all_type_dic.items(), key=lambda x: x[:-1], reverse=True)[:4]
curr_type = '/'.join([s_t[0] for s_t in sorted_type])
fill_null_vakue_list.append(curr_type)
movie_type_null['movie_type'] = fill_null_vakue_list
# 提取需要保存的列
result_df = movie_type_null[['movie_name', 'director', 'editor', 'actor', 'movie_type']]
result_df.to_csv('./deal_date/type_fill.csv', index_label='ID')
def get_list(not_na_df,fill_key): #获取包含fill_key的所有数据,将包含了fill_key的
result_list=[]
for _,i in not_na_df[not_na_df['city'].str.find(fill_key) != -1].iterrows():#找出存在指定字符的数据行
result_list.extend(i.weather.split('/'))#将数据按照/分割
return result_list
fill_list=[]
for _,n in na_df.iterrows():
score_dic ={}#计算总分
name1_list=n.city.split('/')#对数据进行分割计算每一个名字
for name in name1_list:#计算每一个名字
weather_list=get_list(not_na_df,name)#得到非空数据中city列中包含 空值行name1 的所有weather列数据
for i in weather_list:
if i not in score_dic:#判断 i 是否存在于score_dic中
score_dic[i] =0 #添加到字典中
score_dic[i] +=1#累加分数
se=pd.Series(score_dic).sort_values(ascending=False).head(4)#取数量最多的前四位
fill_list.append('/'.join(se.keys().to_list()))#拼接数组添加到list中
df.loc[df['weather'].isna(),'weather']=fill_list #填充数据
df.to_csv('./data/data.csv',index_label='id') #保存结果
填充数据
-
- pd.merge(city_df, days, left_on='date', right_on='date', how='right')#横向拼接,how指定主表
-
- pd.concat(new_list)#水平拼接
days = pd.date_range(start='2011-01-01', end='2022-04-30', freq='D').to_frame(name='date').astype({'date': 'str'})
new_list = []
for city in df['city'].unique():
city_df=df[df['city']==city]
merge_df = pd.merge(city_df, days, left_on='date', right_on='date', how='right')#横向拼接,how指定主表
merge_df['city']=city
new_list.append(merge_df)
full_df=pd.concat(new_list)#水平拼接
full_df['month_day']=full_df['date'].str[5:]
group_df=full_df.groupby(['city','month_day']).agg({
'hightest_tem':lambda x:round(x.mean(),2),
'lowest_tem':lambda x:round(x.mean(),2),
'weather':lambda x:x.mode()[0],
'wind_direction':lambda x:x.mode()[0],
'wind_level':lambda x:x.mode()[0],
})
mode() 众位数 #用于获取出现次数最多的文字
max() 最大值 #用于获取一组数字数据中的最大值
min() 最小值
mean() 平均值
sum() 求和
count() 统计
当分组后的数据一整年都没有对应的数据时。就需要对空值数据进行填充
group_df['lowest_tem'] = group_df['lowest_tem'].fillna(group_df['lowest_tem'].mean())
group_df['weather'] = group_df['weather'].fillna(group_df['weather'].mode()[0])
在原表中筛选有空值的列,根据city和month_day做为索引, 将要填充的数据列添加到列表中,使用loc进行数据填充
def fill_na(full_df,group_df,column):
arr=[]
for i,j in full_df[full_df[column].isna()].iterrows():
arr.append(group_df.loc[j.city,j.month_day][column])
print(len(arr))
full_df.loc[full_df[column].isna(),column]=arr
fill_na(full_df,group_df,'hightest_tem')
df.set_index('id')#将index设置为id
该种数据进行处理的关键
-
- 空值
-
- 异常数据类型数据
-
- 切割后数据列表的数据长度
-
- .str 会将空值转换为''空字符串
wind_direction,wind_level=[],[] #存放处理后的数据
# 南风 3级
for i in df['wind'].str.split(' '):
try:
if i[0] =='' and len(i)!=2:#如果字符串为空或切割后的数据列表长度不为2
wind_direction.append(None)
else:
wind_direction.append(i[0])
except:
wind_direction.append(None)
try:
if i[1] =='' and len(i)!=2:
wind_level.append(None)
else:
wind_level.append(i[1])
except:
wind_level.append(None)
df['wind_direction']=wind_direction #覆盖原数据
df['wind_level']=wind_level
温度列数据处理
#已知存在空值
#hightest_tem 2
#lowest_tem 3
#异常数据
#15℃
#℃
#极端异常数据
#-212℃
#最高温度小于最低温度
数值转换处理
该种数据进行处理的关键
-
- .str会将空值替换为''空字符串
-
- ℃字符
-
- 空值
-
- 数值转换
hightest_tem,lowest_tem=[],[]
for i in df['hightest_tem'].str.replace('℃',''):
try:
if i=='':
hightest_tem.append(None)
else:
hightest_tem.append(round(float(i),2))#转为float,四舍五入两位小数
except:
hightest_tem.append(None)
def lowest_tem_replace(x):
try:
x=x.replace('℃','')#对℃进行替换删除
if x=='': #处理只有℃的数据
return None
else:
return round(float(x),2) #转为float类型,四舍五入保留两位小数
except:
return None #nan空值无法转换为float,引发异常
df['lowest_tem']=df['lowest_tem'].apply(lowest_tem_replace)
异常值处理
df.loc[df['lowest_tem']==df['lowest_tem'].min(),'lowest_tem']=None
diff=full_df['hightest_tem']<full_df['lowest_tem']
hightest_tem_diff=[]
lowest_tem_diff=[]
for i,j in full_df[diff].iterrows():
hightest_tem_diff.append(j.lowest_tem)
lowest_tem_diff .append(j.hightest_tem)
full_df.loc[diff,'hightest_tem']=hightest_tem_diff
full_df.loc[diff,'lowest_tem']=lowest_tem_diff
print('异常值:',len(full_df[full_df['hightest_tem']<full_df['lowest_tem']]))
数据可视化
Pyecharts绘图Graph关系图
-
- curve 线条弯曲
-
- symbol_size 节点大小
-
- repulsion 排斥力
-
- edge_symbol=['circle', 'arrow'], #线条连接处图标
-
- edge_symbol_size=[0, 5], #头尾图标大小
GraphNode:#关系图的节点数据项
name="结点1" #数据项名称
symbol_size: Union[Numeric, Sequence, None] = None,
itemstyle_opts=opts.ItemStyleOpts(
)
#该类目节点标记的大小,可以设置成诸如 10 这样单一的数字,也可以用数组分开表示宽和高,例如 [20, 10] 表示标记宽为 20,高为 10。
GraphLink:#节点间的关系数据
source: Union[str, int, None] = #None:边的源节点名称的字符串,也支持使用数字表示源节点的索引;
target="结点2"#边的目标节点名称的字符串,也支持使用数字表示源节点的索引
value=3:#边的数值,可以在力引导布局中用于映射到边的长度;
linestyle_opts=opts.LineStyleOpts(
curve=0.1#弯曲
width=6
) #关系边的线条样式。
获取共同演过同一场戏的演员
dic2 = {}
names = set(df[0].tolist() + df[1].tolist())#获取全部名字里面不重复的
for name in names:
graph_list=[]
for _,i in df.iterrows():
graph_list.extend(i.to_list())
data=set(graph_list)
data.discard(name)#在演员关系中删除演员自身的名字
dic2[name]=data
dic = {}
for item in df.values:#遍历每一列演员数据
# print(item)
actor_set = set(item)#将一整列演员list添加到set中去重
for actor in item: #遍历演员list
if actor not in dic: #如果演员不存在与set字典中
dic[actor] = set()#向字典添加改名演员 值为set() 用于去重
dic[actor].update(actor_set - {actor}) #将set去重列表中演员自身删除,updata添加到字典中,
nodes = []
init_symbol_size = 50
for i in dic:
nodes.append(GraphNode(name=i,#节点名
symbol_size=init_symbol_size,#节点大小不断衰减
itemstyle_opts=opts.ItemStyleOpts(
color='cyan',
border_color='#000',
border_width=0.1
)))
init_symbol_size -= 5
init_symbol_size = max(init_symbol_size, 10)
links=[]
init_width = 10
for name, data in zip(dic.keys(), dic.values()):
for j in data:
links.append(GraphLink(source=name,#起始节点名称
target=j, #要连接的节点名称
value=2,
linestyle_opts=opts.LineStyleOpts(
is_show=True,
curve=0.1, #弯曲
width=init_width, #宽度不断衰减
opacity=0.5, #透明度
)))
init_width -= 0.5
init_width = max(init_width, 3)
graph = (
Graph(init_opts=opts.InitOpts(
width='100%',
height='800px',
))
.add(
'',
nodes, lines,
repulsion=150, #排斥力
edge_length=60, #关系线长度
edge_symbol=['circle', 'arrow'], #线条连接处图标
edge_symbol_size=[10, 15], #头尾图标大小
label_opts=opts.LabelOpts(
is_show=True,
color='#000',
)
)
.set_global_opts(
title_opts=opts.TitleOpts(
title='演员关系图',
pos_left='center',
pos_top='10px'
)
)
).render()
matplotlib绘图
from matplotlib import pyplot as plt
plt.rcParams['font.family'] = 'SimHei' # 中文显示
color=plt.get_cmap('Accent')(range(len(heights1)))#添加颜色
rotation=45 #倾斜角度
plt.savefig()#保存图片
bbox_to_anchor=[1,1]#图例为定位
plt.figure(figsize=(20,10),facecolor='cyan')#外边框部分的颜色
# ax1=plt.subplot(221)#2行2列中的第一个图
plt.bar(d1['date'],
d1['hightest_tem'],
label='label1',#添加图例表情
)
# plt.set_title('子图1')
# ax2=plt.subplot(223)#2行2列中的第二个图
# plt.bar(
# d2['date'],
# d2['lowest_tem'],
# label='label2',#添加图例label
# )
plt.legend(
fontsize=18,#字体大小(会将图例框撑大)
# loc='upper right', #图例位置(默认值best)
bbox_to_anchor=[0.15,1,0,0]#x,y,x2,y2 图例位置定位
) #显示图例
plt.xticks(ticks=d1['date'],fontsize=20)#数据轴刻度
plt.yticks(ticks=range(-10,50,5),
fontsize=20,
color='red',
ha='right',#默认right对齐
)#数据轴刻度
plt.axis([-1,10,0,50]) #x1~x2,y1,y2
# plt.xlim(-15,55)#轴刻度范围
# plt.ylim(-15,55)#轴刻度范围
plt.title('标题',#标题
fontsize=40,#文字大小
loc='center',#位置
)
plt.suptitle(
'副标题',
y=1,#位置 0~1表示距离底部的距离
fontsize=30,
)
plt.xlabel('x轴标签',fontsize=20,color='g',rotation=45,)#倾斜角度
plt.ylabel('y轴标签',fontsize=20,color='g',rotation=45,)#倾斜角度
for a,b in zip(d1['date'],d1['hightest_tem']):#在数据点上绘制文字
# print(a,b)
plt.text(a,b,
s=f'{b}',
fontsize=30,
color='red',
ha='center',#水平 对齐方式
va='bottom'#垂直 对齐方式
)#绘制文字
plt.savefig('test.png',
pad_inches=1,#内边距
)
plt.show()
y_height = [10, 8, 9, 5, 4, 6]
x_labels = list(range(1, len(height) + 1))
plt.figure(figsize=(20, 10)) #设置画布大小
plt.subplot(1, 2, 1) ##1行,2列 第一张图
plt.title('title1', fontsize=20) #标题
plt.xlabel('label1', fontsize=20) #标签
plt.bar(
x_labels, y_height, #x轴标签,y轴数据
color=plt.get_cmap('Accent')(range(len(heights1)))#柱条颜色 添加颜色
label='data1', #图例标签
) #绘制图像
plt.legend(fontsize=20,
bbox_to_anchor=[1, 1, 0, 0], #图例位置
) #图例
plt.xticks(range(1, 10), fontsize=20, rotation=45) #x刻度
plt.yticks(range(0, 15), fontsize=20, rotation=45) #y刻度
for i in range(0, len(height)):
plt.text(i+1, height[i], f"{height[i]}", fontsize=20,ha='center',va='bottom')
plt.subplot(122) #1行2列 第二张图
plt.bar(x, y, #可传入和y数据长度一致的标签数据
label='data2',
)
for i in range(0,len(y)):
plt.text(i,y[i],f'{y[i]}',fontsize=20,ha='center')
plt.legend(fontsize=20, bbox_to_anchor=[1,1])
plt.title('title2',fontsize=20)
plt.xlabel('x轴标签',fontsize=20)
plt.ylabel('y轴标签',fontsize=20)#垂直 对齐方式
plt.yticks(range(1,150,10),fontsize=20)
plt.xticks(x,fontsize=20,rotation=45)
plt.savefig('2.png')
机器学习
流程简要
特征提取
-
- 提取特征
-
- 提取首位导演,编剧,地区,语言
-
- 添加第一主演,添加主演人数,
-
- 年代 分割日期获取年代,进行年代分段
-
- 电影类型 恐怖归位惊悚,影片类型词频数量小于100的归为 其他
-
- 保存json数据 什么类型 变为 其他
-
- 对需要的列重新构建为一个df
数据编码
-
- 2.使用encoder对每一列进行转换(字符串的使用labelencoder)
-
- 3.把X和y切分出来 y = 目标列,X = 除了目标列以外的列
-
- 4.对X进行归一化(可以把归一化前的直接覆盖掉 ,免得你们用错X)
-
- 保存数据
模型训练
-
- 5.划分训练集和测试集
-
- 6.训练模型
-
- 6.在训练集和测试集进行评估
数据预测
-
- 1.对新数据进行处理(与特征提取一致)
-
- 提取特征(提取第一主演,进行年份分段)
-
- 加载标签编码器、标准化、模型
-
- 2.使用encoder对每一列进行转换(字符串的使用labelencoder)
-
- 3.X = 全部(一般不会给你们y了,你们自己看,如果有y还是得把X提取出来)
-
- 4.对X进行归一化(标准化)
-
- 5.使用训练好的模型进行预测
-
- 6.按照题目要求写入预测结果
特征提取
小于100词频数据填充
import json
def vc_fill(df, column):
vc = df[column].value_counts() #对指定列进行词频统计
vc_100 = vc[vc < 100] #对词频小于100的数据进行筛选
dic = {} #记录什么标签变成了其他标签
for key in vc_100.keys(): #对筛选后的数据的key进行遍历
dic[key] = '其他' #向字典添加数据
df.loc[df[column]==key,column]='其他' #数据填充
with open('./fill_dic/dic.join', 'w+', encoding='utf-8') as f: #必须为w模型,编码指定utf-8
json.dump(dic, f, ensure_ascii=False) #ensure_ascii=False否则无法正常显示
vc_fill(df, 'wind_direction') #传入要填充的df和要进行处理的列名
with open('./fill_dic/dic.join', 'w+', encoding='utf-8') as f: #必须为w模型,编码指定utf-8
json.dump(dic, f, ensure_ascii=False) #ensure_ascii=False否则无法正常显示
with open('./vc_dic/vc_dic.json', 'r+', encoding='utf-8') as f:#词频字典
vc_dic = json.load(f)
#{'雪': '其他', '霾': '其他'}
def vc_fill(x):
if x in vc_dic.keys():
return vc_dic[x]
else:
return x
df['day1_weather']=df['day1_weather'].apply(vc_fill)
数据分割提取首位
需确保数据中不存在空值
#2022-04-29
df['date'].str.split('-').apply(lambda x:x[0])#对需要分割的数据使用split('-')分割,对得到的列表取第[0]索引
df.loc[df['wind_direction']=='微风']='无持续风向'
标签编码器
要求只对非数字型数据进行处理 int 和 np.int64 不一样需要注意
#要求只对非数字型数据进行处理
if type == int or type == float or type == np.int64 or type == np.int32 or type == np.float64 or type ==np.float32:
encoder=MyEncoder()
else:
encoder=LabelEncoder()
通过引发数值转化异常来判断是否为数值型
for i in df.columns:
try:
df[i].astype(int) #对列数据进行转换,引发异常
encoder = MyEncoder() #数字型
except: #纯数字组成的字符串
encoder = LabelEncoder() #字符型
class MyEncoder():
def fit_transform(self, x):#训练编码器
return x
def transform(self,x):#进行编码
return x
def inverse_transform(self,x):#将编码后的数据还原
return x
from sklearn.preprocessing import LabelEncoder
def fit_encoder(df):
encoders=[]
for i in df:
try:
df[i].astype(float)
encoder=MyEncoder()
except:
encoder=LabelEncoder()
df[i]=encoder.fit_transform(df[i])
encoders.append(encoder)
with open('./encoders/encoders.pkl','wb+') as f:
pickle.dump(encoders,f)
标准化
根据题意使用即可
-
- MinMaxScaler() 归一化
-
- StandardScaler() 标准化
from sklearn.preprocessing import StandardScaler
def fit_st(df):
x_columns = ['day1_high_tem', 'day1_low_tem', 'day1_weather', 'day1_wind', 'day1_month'] #假定需要处理的x列
st = StandardScaler() #创建对象
X = st.fit(df[x_columns]) #进行标准化
df[x_columns]=X#将标准化后的数据直接覆盖原数据
with open('./st/st.pkl', 'wb+') as f: #保存
pickle.dump(st, f)
模型模型与模型评估
训练集测试集划分 x_train,x_test,y_train,y_test=train_test_split(x,y,random_state=7,test_size=0.2) xxyy tr te tr te
RandomForestRegressor随机森林回归模型
关键参数:
-
- n_estimators=1000,
-
- max_depth=10,
-
- max_features=8,
-
- min_samples_split=5,
from sklearn.metrics import r2_score #决定系数
from sklearn.metrics import mean_squared_error #均方误差
from sklearn.ensemble import RandomForestRegressor # 随机森林回归
from sklearn.model_selection import train_test_split #训练集测试集划分
x_train,x_test,y_train,y_test=train_test_split(x,y,random_state=7,test_size=0.2)
model=RandomForestRegressor(n_estimators=1000,max_depth=10,max_features=8)
model.fit(x_train,y_train)
在回归模型中score和r2_score分数应该一致 model.score要传入的是x,y r2_score要传入的是真实值和预测值
print(model.score(x_test,y_test)) #传入x,y
print(r2_score(y_test,model.predict(x_test))) # 传入真实值和预测值
print(mean_squared_error(y_test,model.predict(x_test)))# 传入真实值和预测值
新数据预测
标签编码器和标准化都需要使用encoder.transform(X) 来进行数据处理 使用MyEncoder的编码器需要导入
import pickle
from MyEncoder import MyEncoder
with open('./encoder_data/encoder_data.pkl','rb+') as f:#标签编码
encoders=pickle.load(f)
with open('./scaler_data/scaler_data.pkl','rb+') as f:#标准化
st=pickle.load(f)
st_x=st.transform(all_data)
with open('./models_data/model.pkl','rb+') as f:#模型
models=pickle.load(f)
-
- 导入pkl
-
- 导入要预测的数据
-
- 标签编码
-
- 标准化
-
- 模型预测
from MyEncoder import MyEncoder
import pickle
import pandas as pd
#加载pkl模型
with open('./enconders_data/enconders_data.pkl', 'rb+') as f:
encoders = pickle.load(f)
with open('./scaler_data/scaler_data.pkl', 'rb+') as f:
st = pickle.load(f)
with open('./model_data/model.pkl', 'rb+') as f:
model = pickle.load(f)
#读取要预测的文件
df = pd.read_csv('./data/feature/长沙_feature.csv')#读取长沙数据
df['city']='北京'#city改为北京
for i, encoder in zip(df, encoders):#标签编码
df[i] = encoder.transform(df[i])
x_columns = [#列出需要标准化的数据
'city',
'day1_high_tem', 'day1_low_tem', 'day1_weather', 'day1_wind', 'day1_month',
'day2_high_tem', 'day2_low_tem', 'day2_weather', 'day2_wind', 'day2_month',
'day3_high_tem', 'day3_low_tem', 'day3_weather', 'day3_wind', 'day3_month',
'day4_high_tem', 'day4_low_tem', 'day4_weather', 'day4_wind', 'day4_month',
'day5_high_tem', 'day5_low_tem', 'day5_weather', 'day5_wind', 'day5_month',
'day6_high_tem', 'day6_low_tem', 'day6_weather', 'day6_wind', 'day6_month',
'day7_high_tem', 'day7_low_tem', 'day7_weather', 'day7_wind', 'day7_month',
]
X = st.transform(df[x_columns])#标准化
# data_df = pd.DataFrame(X, columns=x_columns)#构建新df
df[x_columns]=X
x = data_df[[
'day1_high_tem', 'day1_weather', 'day1_wind', 'day1_month',
'day2_high_tem', 'day2_weather', 'day2_wind', 'day2_month',
'day3_high_tem', 'day3_weather', 'day3_wind', 'day3_month',
'day4_high_tem', 'day4_weather', 'day4_wind', 'day4_month',
'day5_high_tem', 'day5_weather', 'day5_wind', 'day5_month',
'day6_high_tem', 'day6_weather', 'day6_wind', 'day6_month',
'day7_high_tem', 'day7_weather', 'day7_wind', 'day7_month',
]]#预测数据
y = df['cur_high_tem'].values.reshape(len(df['cur_high_tem']))#真实结果结果数据
from sklearn.metrics import r2_score
print(model.predict(x))
print(model.score(x, y))#0.8495963922917477
print(r2_score(y, model.predict(x)))#0.8495963922917477
非特殊说明,本博所有文章均为博主原创。
如若转载,请注明出处:https://cpxigxs.cn/2024/04/15/8/
共有 0 条评论