DAY6:Kaggle-San Francisco Crime Classification(上)

大家好,今天来到第六天了~完成1/5了,必须说参加铁人赛还都完赛的人,真的很棒很有毅力,花自己工作之余的休息时间来分享自己的学习历程,这边我给自己一个肯定哈哈哈哈!!我会努力把30天写完的!!

  • 资料来源和问题确认

今天这个题目呢,是我去年在资策会的时候想要自己练习做资料分析去Kaggle找到的一个题目,它是一堆犯罪纪录,而我们要拿这些资料去预测它的test资料集是哪种犯罪类型,很好玩吧,是一个多分类的问题,不像前几天做的都是二分类的问题。
kaggle传送门

  • 导入资料及资料前处理

第一步一定是导入我们的资料啦~我们一样用pandas套件的read_csv来导入资料。

import pandas as pd

train=pd.read_csv('./train.csv')
test=pd.read_csv('./test.csv')

再来我们看看资料型态长怎样。

print(train.head(5))

我们来解释一下它的各个资料栏位的意思,在train资料里面总共有9个栏位,分别为:
 1. Dates:犯罪事件的时间戳。
 2. Category:犯罪事件的类型。(也就是我们要预测的Y)
 3. Descript:对於犯罪的描述。
 4. DayOfWeek:犯罪是在星期几。
 5. PdDistrict:警察局管辖区域名称。
 6. Resolution:犯罪是如何被解决的。
 7. Address:犯罪发生的大致街道地址。
 8. X:犯罪位置的经度。
 9. Y:犯罪位置的纬度。

接下来我们看看test资料里面有哪些特徵栏位。

print(test.columns)

分别为:
 1. Id:编号ID。
 2. Dates:犯罪事件的时间戳。
 3. DayOfWeek:犯罪是在星期几。
 4. PdDistrict:警察局管辖区域名称。
 5. Address:犯罪发生的大致街道地址。
 6. X:犯罪位置的经度。
 7. Y:犯罪位置的纬度。

所以我们可以先做第一件事情就是把没出现在test的特徵栏位删除,所以我们将train里面的"Descript"及"Resolution"这两个特徵删除。"Category"则是我们训练时需要用到的应变数。

train.drop(['Descript','Resolution'],inplace=True,axis=1)

print(train.head(5))

查看有没有缺失值,发现资料并无缺失值。

print(train.isnull().sum())
print(test.isnull().sum())

 train       test

接下来,在Dates的地方,我想把这个栏位再分的更细一点,年、月、时和分给区隔开来,日期我没有分出来,我认为日期对我们要预测的应变数影响不大。还有Address的部分,若有含街道block的部分,我把它显示为布林值。这里DayOfWeek我们自己再做一次,怕原本资料写错,且原资料给的星期几是类别变数,我们也直接将它转成虚拟变数。

def build_datetime_and_block(df):
    df['Dates'] = pd.to_datetime(df['Dates'])
    df['Date'] = df['Dates'].dt.date
    df['Hour'] = df['Dates'].dt.hour
    df['Minute'] = df['Dates'].dt.minute
    df['DayOfWeek'] = df['Dates'].dt.weekday
    df['Month'] = df['Dates'].dt.month
    df['Year'] = df['Dates'].dt.year
    df['Block'] = df['Address'].str.contains('block', case=False)#case预设=True,表示区分大小写。
    return df
train = build_datetime_and_block(train)
test = build_datetime_and_block(test)

我们已经把Dates和Address给分的更细了,那这些特徵就不需要了,将他们删除。

train.drop(['Address','Dates','Date'],inplace=True,axis=1)
test.drop(['Address','Dates','Date'],inplace=True,axis=1)

print(train.head(5))
print(test.head(5))

train

test

处理完上面的特徵,我们来看看剩下"PdDistrict"和经纬度("X"、"Y")没有动到,先来看看"PdDistrict"有没有其他的问题,已经检视过没有缺失值了。

print(train.PdDistrict.unique())

看起来也没有其他问题。

再来看看经纬度吧!

这里我们会用到geopandas这个套件,我自己安装的时候是有遇到一些问题,可以参考这里去安装。

from shapely.geometry import Point
import geopandas as gpd

def create_gdf(df):
    gdf = df.copy()
    gdf['Coordinates'] = list(zip(gdf.X, gdf.Y))
    gdf.Coordinates = gdf.Coordinates.apply(Point)
    gdf = gpd.GeoDataFrame(
        gdf, geometry='Coordinates', crs={'init': 'epsg:4326'})
    return gdf

train_gdf = create_gdf(train)

world = gpd.read_file(gpd.datasets.get_path('naturalearth_lowres'))
ax = world.plot(color='white', edgecolor='black')
train_gdf.plot(ax=ax, color='red')
plt.show()

可以发现最上面那个红点明显偏离了,代表有经纬度是给错的。

我们将经纬度照顺序列出来,看到X = -120.5和Y = 90.0这两个变数属於离群值。

print(sorted(list(train.X.unique()),reverse=True))
print(sorted(list(train.Y.unique()),reverse=True))

X            Y

先观察笔数多寡,可以发现当X = -120.5时,Y = 90.0,train都是67笔,而test是76笔。

wrongxy = lambda df : len(df[(df['X'] == -120.5) & (df['Y'] == 90.0)])
print(wrongxy(train))
print(wrongxy(test))

wrongxy = lambda df : len(df[(df['X'] == -120.5)])
print(wrongxy(train))
print(wrongxy(test))

wrongxy = lambda df : len(df[(df['Y'] == 90.0)])
print(wrongxy(train))
print(wrongxy(test))

我们可选择删除或是改动值的方式,这边我选择依照PdDistrict的经纬度的中位数去改这些值。

def fix_gps(df):
    n = 0
    d = df[(df['X'] == -120.5) & (df['Y'] == 90.0)]
    for idx, row in d.iterrows():
        district = row['PdDistrict']
        xys = df[df['PdDistrict'] == district][['X', 'Y']]
        #print("PdDistrict:", district)
        df.loc[idx, ['X']] = xys['X'].median()
        df.loc[idx, ['Y']] = xys['Y'].median()
        #print(df.loc[idx, ['X']].values[0], df.loc[idx, ['Y']].values[0])
        n = n + 1
    print('更动几笔资料:', n)
fix_gps(train)

fix_gps(test)


  • 今日小结

今天主要对资料做清洗,对於每个特徵,都较详细的去处理他们,并且有搭配到用地图去看经纬度资料是否有误。资料前处理部分剩下一部分,主要是这次的资料很多为类别变数,我们需要帮它转换成虚拟变数,文字变成数字,这样才能丢进模型建模,那我们明天就来处理剩下的部分吧!!这次的模型,除了用之前的sklearn套件以外,还会尝试用tensorflow去建立神经网路来建模,开始要接触深度学习罗!!
那我们明天见~


<<:  # Day 12 Cache and TLB Flushing Under Linux (四)

>>:  DAY9-OH CRUD.

[android studio]Java 自定义对话框中的客制ListView

1 今天试着把预设的对话框选单改变成自定义画面,把原本使用.setItems呈现的预设对话框主题,使...

[Day 5] Ktor 微框架就如同一间毛胚屋,先来列出想要整合的框架及实作的功能清单

Ktor 的架构设计及开发风格是我所喜欢的,但相对地使用 Ktor 开发也要付出代价。因为 Ktor...

【Day25】反馈元件 - Skeleton

元件介绍 Skeleton 是一个骨架载入元件(Skeleton Screen Loading),跟...

[Day 29] Laravel+MongoDB+Vue CRUD - part 2

Day28已建立好环境了,接下来开始制作CURD功能罗~ Controller php artisa...

Day 0xA UVa490 Rotating Sentences

Virtual Judge ZeroJudge 题意 将输入的多行字串改变顺序後输出 需要注意的点...