数据分析+数据可视化+机器学习笔记

2024-4-15 344 4/15

笔记

' 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

    1. 使用strip对字符串两端进行去除空格
    1. 对为空字符串的数据不做处理(默认值数据)
    1. 将-替换为/
    1. 对根据(对字符串进行划分,取0索引(去除日期(时区)的情况)
    1. 取前3索引,应为y,m,d
    1. 根据前3列表长度判断,年月日是否有空缺
    1. 对月份是英文缩写的情况单独进行处理,使用datetime.strptime()对月份格式进行处理
    1. 将得到的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

电影类型填空

难点
    • 定位包含指定名字的行
    • 获取类型列表
    • 权重累加
流程
    1. 首先先将数据分为电影类型列 有空值(isna)和无空值(notna)的2组数据
    1. 创建存放结果数据的fill_null_vakue_list列表
    1. 遍历每一个电影类型列有空值的行
    1. 对导演、主编、演员(取前三位)使用/划分得到名字列表
    1. 接着根据每一个导演、主编、演员的名字在无空值的数据中寻找他们都参演过什么类型的电影 将参演过的电影类型全部存入列表返回 ['恐怖','爱情','校园','科幻','恐怖','恐怖']
#找得到返回索引
#找不到会返回-1
for i in not_na_df[not_na_df['city'].str.find(fill_key) != -1].values:
    print(i)
    1. 通过字典统计计算权重分值 遍历 参演过电影类型列表 中的每一个电影类型名称 如果没存在于字典中就添加为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)
#'恐怖/爱情/校园/科幻'
    1. 添加到fill_null_vakue_list列表中
    1. 构建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)

标准化

根据题意使用即可

    1. MinMaxScaler() 归一化
    1. 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)
    1. 导入pkl
    1. 导入要预测的数据
    1. 标签编码
    1. 标准化
    1. 模型预测
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
- THE END -
Tag:

dajavv

9月09日03:25

最后修改:2024年9月9日
1

非特殊说明,本博所有文章均为博主原创。

共有 0 条评论