首先先说一下编程的工具
数据集中的每一行记录了一起恐怖袭击事件的信息,分为以下几部分进行了记录:
关于数据集的问题:
关于机器学习,深度学习模型的问题:
对于题目中让我们解决的几个任务的处理:
(以下是代码部分)
# 数据处理
import numpy as np
import pandas as pd
import warnings
# 忽略警告
warnings.filterwarnings('ignore')
# 设置pandas显示属性
pd.set_option('display.max_columns', 20)
# 读取Excel数据集
data = pd.read_excel('1993.xlsx')
# # 查看两行数据
# print(data.head(2))
# # 查看数据的列索引
# print(data.columns)
# 按照不同类别字段切分表
# GTD的标志号和日期
# copy()保证不影响原先表
data_of_GTD = data.iloc[:, :7].copy()
# 事件发生的地点
data_of_location = data.iloc[:, 7:18].copy()
# 事件信息
# 这里根据包含的字段名进行获取,中间有间断,无法进行切片
# DataFrame['name']:获取name列的值
# DataFrame[['name1','name2',...]]:获取多列的值
data_of_info = data[
['summary', 'crit1', 'crit2', 'crit3', 'doubtterr', 'alternative', 'alternative_txt', 'multiple', 'related']].copy()
# 攻击信息
# 索性都用字段名吧
# 前面突然来了一个间断断了节奏,好烦
# 要索引的字段中重复的字段
# 用列表自己生成
sup_list = [['attacktype' + str(i), 'attacktype' + str(i) + '_txt'] for i in range(1, 4)]
# 要索引的列
index_columns = ['success', 'suicide']
index_columns += sup_list[0]
index_columns += sup_list[1]
index_columns += sup_list[2]
data_of_attack = data[index_columns].copy()
# 也可以
# data_of_attack = data[
# ['success', 'suicide', 'attacktype1', 'attacktype1_txt', 'attacktype2', 'attacktype2_txt', 'attacktype3',
# 'attacktype3_txt']].copy()
# 目标/受害者信息
sup_list = [['targtype' + str(i), 'targtype' + str(i) + '_txt', 'targsubtype' + str(i), 'targsubtype' + str(i) + '_txt',
'corp' + str(i), 'target' + str(i), 'natlty' + str(i), 'natlty' + str(i) + '_txt'] for i in range(1, 4)]
index_columns = []
index_columns += sup_list[0]
index_columns += sup_list[1]
index_columns += sup_list[2]
data_of_target = data[index_columns].copy()
# 凶手信息
index_columns = ['gname', 'gsubname']
sup_list = [['gname' + str(i), 'gsubname' + str(i)] for i in range(2, 4)]
index_columns += sup_list[0]
index_columns += sup_list[1]
index_columns.append('motive')
sup_list = [['guncertain' + str(i)] for i in range(1, 4)]
index_columns += sup_list[0]
index_columns += sup_list[1]
index_columns += sup_list[2]
index_columns.append('individual')
index_columns.append('nperps')
index_columns.append('nperpcap')
index_columns.append('claimed')
index_columns.append('claimmode')
index_columns.append('claimmode_txt')
sup_list = [['claim' + str(i), 'claimmode' + str(i), 'claimmode' + str(i) + '_txt'] for i in range(2, 4)]
index_columns += sup_list[0]
index_columns += sup_list[1]
index_columns.append('compclaim')
data_of_murder = data[index_columns].copy()
# 武器信息
index_columns = []
sup_list = [['weaptype' + str(i), 'weaptype' + str(i) + '_txt', 'weapsubtype' + str(i), 'weapsubtype' + str(i) + '_txt']
for i in range(1, 5)]
index_columns += sup_list[0]
index_columns += sup_list[1]
index_columns += sup_list[2]
index_columns += sup_list[3]
index_columns.append('weapdetail')
data_of_weapon = data[index_columns].copy()
# 伤亡和后果
data_of_result = data.iloc[:, 99:125].copy()
# 附加信息和来源
data_of_append = data.iloc[:, 125:135].copy()
# 依次处理每个表
# 1.对于‘GTD的标志号和日期 ’这一类字段信息
# 因为eventid中已经包含了时间信息
# 把后面iyear,imonth,iday等冗余信息删除
# resolution这一列虽然存在很多缺失值
# 但是不应该直接删除
# 因为它反映了恐怖袭击事件持续的时长
# 持续的时间越长,说明这起恐怖袭击事件越恶劣
# 所以将resolution这一列缺失值填为0
# 然后以小时为计时单位进行换算,计算出这起恐怖袭击事件持续的时间
# 获取resolution列非空的行
data_with_resolution = data_of_GTD[data_of_GTD.resolution.notnull()]
# 按照前面所述换算成以小时为单位的持续时间
from datetime import datetime
# 获取事件开始的时间
# 获取resolution列非空行的索引
index_list = data_with_resolution.index
start_time = [str(data_with_resolution['iyear'][index_list[i]]) + '-' + str(
data_with_resolution['imonth'][index_list[i]]) + '-' + str(data_with_resolution['iday'][index_list[i]]) for i in
range(len(data_with_resolution.index))]
# 转换为时间序列
start_time = pd.to_datetime(start_time)
# 获取事件结束的时间,转换为时间序列
end_time = pd.to_datetime(data_with_resolution['resolution'])
# 获取时间差值,以小时为单位存储
time_diff = pd.to_timedelta(end_time - start_time).dt.days * 24
# 修改原表中的数值
# 按照索引来,不能直接赋值
for i in index_list:
data_of_GTD['resolution'][i] = time_diff[i]
# 将resolution列的缺失值设为0
data_of_GTD.resolution.fillna(0, inplace=True)
# 删除iyear,imonth,iday,approxdate,extended列
delete_columns = ['iyear', 'imonth', 'iday', 'approxdate', 'extended']
data_of_GTD.drop(delete_columns, inplace=True, axis=1)
print("处理之后的GTD信息为:")
print(data_of_GTD.head(2))
# 2.对于‘事件发生的地点’这一类字段信息
# contry与contry_txt是一对映射关系,保留contry即可
data_of_location.drop(['country_txt'], inplace=True, axis=1)
# region与region_txt同理
data_of_location.drop(['region_txt'], inplace=True, axis=1)
# provstate,city这两列分类型的文本数据,转换为one_hot编码
# 后面有攻击信息中有一段转换为one-hot编码的代码段,可以类比进行写,这里不写了
# latitude,longitude,specificity表示位置的经纬度,属于冗余信息,且缺失值较多,直接删除
data_of_location.drop(['latitude', 'longitude', 'specificity'], inplace=True, axis=1)
# location这列虽然缺失值较多,但是提供了关于位置,甚至是恐怖袭击的一些信息,需要保留,
# 下一步用自然语言处理的方法进行处理,缺失值可以设置为'UNK'
# data_of_location['location'] = data_of_location['location'].apply(lambda x: 'UNK' if len(str(x)) == 0 else x)
data_of_location.location.fillna('UNK', inplace=True)
print("处理之后的事件发生的地点信息为:")
print(data_of_location.head(2))
# 3.对于‘事件信息’这一类字段信息
# summary需要保留,如果有缺失值设为'UNK'
data_of_info.summary.fillna('UNK', inplace=True)
# crit1,crit2,crit3,doubtterr属于同一个语义域的记录,合并到一起作为一个特征
# 转换为str类型才能连接,否则是加法
data_of_info['crit1_crit2_crit3_doubtterr'] = data_of_info['crit1'].map(str) + data_of_info['crit2'].map(str) + \
data_of_info['crit3'].map(str) + \
data_of_info['doubtterr'].map(str)
data_of_info.drop(['crit1', 'crit2', 'crit3', 'doubtterr'], inplace=True, axis=1)
# 删除alternative,alternative_txt
data_of_info.drop(['alternative', 'alternative_txt'], inplace=True, axis=1)
# multiple这列表示一个恐怖袭击事件组,是有用的特征,但是模型学习的时候可以不考虑
# 因为模型是在一个事件一个事件的进行处理
# 如果后续想以事件组进行考虑可以使用这个特征,暂时删除
data_of_info.drop(['multiple'], inplace=True, axis=1)
data_of_info.drop(['related'], inplace=True, axis=1)
print("处理之后的事件信息:")
print(data_of_info.head(2))
# 4.对于‘攻击信息’这一类字段信息
# 全部保留,分类型的文本数据转为one-hot编码,
# 攻击类型缺失值用10填充
data_of_attack.attacktype1.fillna(10, inplace=True)
data_of_attack.attacktype2.fillna(10, inplace=True)
data_of_attack.attacktype3.fillna(10, inplace=True)
# 攻击类型文本缺失值用UNK填充
data_of_attack.attacktype1_txt.fillna('UNK', inplace=True)
data_of_attack.attacktype2_txt.fillna('UNK', inplace=True)
data_of_attack.attacktype3_txt.fillna('UNK', inplace=True)
# 将文本型的数据转换为one-hot类型的数据
# 获取这一列不同的值
unique_list = data_of_attack['attacktype1_txt'].unique()
# 建立映射字典
unique_value_map = {}
for index, value in enumerate(unique_list):
unique_value_map[value] = index
# 将文本类型转换为分类类型
# 这里只是简单的标记,可以利用scikit-learn真正的转换为one-hot编码
# 但是这样后面就可以处理了,因为已经标记出了不同类别
data_of_attack['attacktype1_txt'] = data_of_attack['attacktype1_txt'].apply(lambda x: int(unique_value_map[x]))
# 获取这一列不同的值
unique_list = data_of_attack['attacktype2_txt'].unique()
# 建立映射字典
unique_value_map = {}
for index, value in enumerate(unique_list):
unique_value_map[value] = index
# 将文本类型转换为分类类型
data_of_attack['attacktype2_txt'] = data_of_attack['attacktype2_txt'].apply(lambda x: int(unique_value_map[x]))
# 获取这一列不同的值
unique_list = data_of_attack['attacktype3_txt'].unique()
# 建立映射字典
unique_value_map = {}
for index, value in enumerate(unique_list):
unique_value_map[value] = index
# 将文本类型转换为分类类型
data_of_attack['attacktype3_txt'] = data_of_attack['attacktype3_txt'].apply(lambda x: int(unique_value_map[x]))
print("处理完之后的攻击信息:")
print(data_of_attack.head(2))
# 5.对于‘目标/受害者信息’这一类字段信息
# 类似于‘攻击信息’的处理方式
# 合并为一个特征
print('处理完之后的目标信息:')
print(data_of_target.head(2))
# 6.对于‘凶手信息’这一类字段信息
# 保留gname列,然后转为one_hot编码
# 其余列全部删除
delete_columns = ['gsubname']
sup_list = [['gname' + str(i), 'gsubname' + str(i)] for i in range(2, 4)]
delete_columns += sup_list[0]
delete_columns += sup_list[1]
delete_columns.append('motive')
sup_list = [['guncertain' + str(i)] for i in range(1, 4)]
delete_columns += sup_list[0]
delete_columns += sup_list[1]
delete_columns += sup_list[2]
delete_columns.append('individual')
delete_columns.append('nperps')
delete_columns.append('nperpcap')
delete_columns.append('claimed')
delete_columns.append('claimmode')
delete_columns.append('claimmode_txt')
sup_list = [['claim' + str(i), 'claimmode' + str(i), 'claimmode' + str(i) + '_txt'] for i in range(2, 4)]
delete_columns += sup_list[0]
delete_columns += sup_list[1]
delete_columns.append('compclaim')
data_of_murder.drop(delete_columns, inplace=True, axis=1)
# 第一问暂时用不到这类信息
# 因为即使是同一个凶手做的恐怖袭击事件,你也无法保证每次所做的恐怖袭击事件是同样的级别
print("处理完之后的凶手信息:")
print(data_of_murder.head(2))
# 7.对于‘武器信息’这一类字段信息
# 删除掉weapdetail这一列
data_of_weapon.drop(['weapdetail'], inplace=True, axis=1)
# 其余的列如果是数值型直接保留,如果是分类型的文本数据转换为one-hot编码的形式
print("处理完之后的武器信息:")
print(data_of_weapon.head(2))
# 8.对于‘伤亡和后果’这一类字段信息
# propextent的缺失值设置为4
data_of_result.propextent.fillna(4, inplace=True)
# 删除propextent_txt,propvalue,propcomment
# nhostkid,nhostkidus,nhours,ndays,divert
# kidhijcountry,ransom,ransomamt
# ransomamtus,ransompaid,ransomnote,hostkidoutcome_txt,nreleased
delete_columns = [
'propextent_txt', 'propvalue', 'propcomment',
'nhostkid', 'nhostkidus', 'nhours', 'ndays',
'divert', 'kidhijcountry', 'ransom',
'ransomamt', 'ransomamtus', 'ransompaid',
'ransomnote', 'hostkidoutcome_txt', 'nreleased'
]
data_of_result.drop(delete_columns, inplace=True, axis=1)
print("处理完之后的事件结果信息:")
print(data_of_result.head(2))
# 9.对于‘附加信息和来源’这一类字段信息
# 合并addnotes,scite1,scite2,scite3到一列
# 合并INT_LOG,INT_IDEO,INT_MISC,INT_ANY到一列
data_of_append.addnotes.fillna('UNK', inplace=True)
data_of_append.scite1.fillna('UNK', inplace=True)
data_of_append.scite2.fillna('UNK', inplace=True)
data_of_append.scite3.fillna('UNK', inplace=True)
data_of_append['addnotes_scite1_scite2_scite3'] = data_of_append['addnotes'].map(str) + data_of_append['scite1'].map(
str) + data_of_append['scite2'].map(str) + data_of_append['scite3'].map(str)
data_of_append.drop('dbsource', inplace=True, axis=1)
data_of_append['INT_LOG_INT_IDEO_INT_MISC_INT_ANY'] = data_of_append['INT_LOG'].apply(lambda x: abs(x)).map(str) + \
data_of_append[
'INT_IDEO'].apply(lambda x: abs(x)).map(str) + data_of_append[
'INT_MISC'].apply(lambda x: abs(x)).map(str) + \
data_of_append['INT_ANY'].apply(lambda x: abs(x)).map(str)
delete_columns = ['addnotes', 'scite1', 'scite2', 'scite3', 'INT_LOG', 'INT_IDEO', 'INT_MISC', 'INT_ANY']
data_of_append.drop(delete_columns, inplace=True, axis=1)
data_of_append.drop(['related'], inplace=True, axis=1)
print('处理完之后的附加信息为:')
print(data_of_append.head(2))