探究冲突趋势和模式:曼尼普尔ACLED数据分析

简介

数据分析和可视化是强大的工具,可以帮助我们理解复杂数据集并有效地传达见解。在这个真实世界冲突数据的深入探索中,我们深入了解冲突的复杂现实和复杂性。我们的焦点是印度东北部的 Manipur 邦,该邦不幸被长期的暴力和动荡所困扰。使用武装冲突位置及事件数据项目(ACLED)数据集[1],我们开始了一段深入的数据分析之旅,以揭示冲突的多方面性。

学习目标

  • 掌握 ACLED 数据集的数据分析技巧。
  • 开发有效的数据可视化技能,以进行沟通。
  • 了解暴力对弱势群体的影响。
  • 获得有关冲突的时间和空间方面的见解。
  • 支持基于证据的方法,以应对人道主义需求。

本文是数据科学博客马拉松的一部分。

利益冲突

在本博客中呈现的分析和解释没有特定的组织或实体负责。目的纯粹是展示数据科学在冲突分析中的潜力。此外,这些发现没有个人利益或偏见参与,确保了对冲突动态的客观处理方式。促进数据驱动的方法作为增强见解和为冲突分析的广泛讨论提供信息的工具。

实施

为什么使用 ACLED 数据集?

通过在 ACLED 数据集上利用数据科学技术,我们可以提取的见解不仅有助于了解 Manipur 的情况,而且还揭示了与暴力有关的人道主义方面。ACLED Codebook 是一份全面的参考指南,提供了有关该数据集中使用的编码方案和变量的详细信息[2]。

ACLED 的重要性在于它的同情心数据分析,它增强了我们对 Manipur 暴力的理解,阐明了人道主义需求,并有助于解决和减轻暴力。它促进了受影响社区的和平和包容的未来。

通过这种数据驱动的分析,我们不仅可以揭示有价值的见解,而且可以凸显 Manipur 暴力的人为代价。通过仔细审查 ACLED 数据,我希望我们可以阐明对平民人口、强制转移和获得基本服务的影响,从而全面描绘该地区面临的人道主义现实。

冲突事件

作为第一步,我们将使用 ACLED 数据集探究 Manipur 的冲突事件。以下代码片段读取印度的 ACLED 数据集,并过滤特定于 Manipur 的数据,从而生成一个形状为(行数,列数)的过滤数据集。然后打印出过滤数据的形状。

import pandas as pd 


# 从 acleddata.com 导入特定国家的 csv

file_path = './acled_India.csv' 

all_data = pd.read_csv(file_path) 



# 筛选 Manipur 的数据 

df_filtered = all_data.loc[all_data['admin1'] == "Manipur"] 

shape = df_filtered.shape 



print("Filtered Data Shape:", shape)

# 输出:  

# Filtered Data Shape: (4495, 31)

ACLED 数据中的行数表示数据集中记录的单个事件或事故的数量。每行通常对应于特定事件,如冲突、抗议或暴力事件,并包含各种属性或列,提供有关事件的信息,如位置、日期、涉及的行动者和其他相关细节。

通过计算 ACLED 数据集中的行数,您可以确定数据中记录的事件或事故的总数。通过专门筛选 Manipur 的数据集,我们获得了一个过滤数据集,其中包含从 2016 年 1 月到 2023 年 6 月 9 日记录的单个事件或事故的信息。 Manipur 记录的事件或事故总数为 4495 行,提供了有关 ACLED 跟踪的冲突或事件的范围和规模的见解。

作为下一步,我们计算 df_filtered DataFrame 中每列的空值总数(axis=0)。它可以提供有关筛选数据集中每个列中缺失值的计数的见解。

df_filtered.isnull().sum(axis = 0) 

# 输出: 每列中的空值总数
# event_id_cnty: 0 个空值
# event_date: 0 个空值
# year: 0 个空值
# time_precision: 0 个空值
# disorder_type: 0 个空值
# event_type: 0 个空值
# sub_event_type: 0 个空值
# actor1: 0 个空值
# assoc_actor_1: 1887 个空值
# inter1: 0 个空值
# actor2: 3342 个空值
# assoc_actor_2: 4140 个空值
# inter2: 0 个空值
# interaction: 0 个空值
# civilian_targeting: 4153 个空值
# iso: 0 个空值
# region: 0 个空值
# country: 0 个空值
# admin1: 0 个空值
# admin2: 0 个空值
# admin3: 0 个空值
# location: 0 个空值
# latitude: 0 个空值
# longitude: 0 个空值
# geo_precision: 0 个空值
# source: 0 个空值
# source_scale: 0 个空值
# notes: 0 个空值
# fatalities: 0 个空值
# tags: 1699 个空值
# timestamp: 0 个空值

以下代码段输出每个列中唯一值的数量。

n = df_filtered.nunique(axis=0) 

print("每个列中的唯一值数量:\n", n)

# 输出:
# 每个列中的唯一值数量:
# event_id_cnty: 4495
# event_date: 1695
# year: 8
# time_precision: 3
# disorder_type: 4
# event_type: 6
# sub_event_type: 17
# actor1: 66
# assoc_actor_1: 323
# inter1: 8
# actor2: 61
# assoc_actor_2: 122
# inter2: 9
# interaction: 28
# civilian_targeting: 1
# iso: 1
# region: 1
# country: 1
# admin1: 1
# admin2: 16
# admin3: 37
# location: 495
# latitude: 485
# longitude: 480
# geo_precision: 3
# source: 233
# source_scale: 12
# notes: 4462
# fatalities: 10
# tags: 97
# timestamp: 1070

使用Folium库创建交互式地图来可视化ACLED事件

曼尼普尔邦在地理上分为两个不同的地区:山谷地区和山地地区。山谷地区位于曼尼普尔邦的中部,相对平坦,被山丘包围。这是邦内人口最密集和农业生产最丰富的地区。另一方面,山地地区包括周围的山丘和山脉,提供了更加崎岖和多山的地形。

下面的代码使用Folium库创建交互式地图,可视化了2022年和2023年曼尼普尔邦发生的ACLED事件。它将事件绘制为地图上的圆形标记,每个标记的颜色表示对应的年份。它还添加了一个GeoJSON图层来显示曼尼普尔邦的边界,并包括地图标题、制作者和一个表示年份颜色代码的图例。最终地图显示所有这些元素。

import folium 

# 为2022年和2023年的数据进行过滤 

df_filtered22_23 = df_filtered[(df_filtered['year'] == 2022) | (df_filtered['year'] == 2023)] 

# 创建一个地图实例 

map = folium.Map(location=[24.8170, 93.9368], zoom_start=8) 

# 从GeoJSON文件中加载曼尼普尔邦的边界 

manipur_geojson = 'Manipur.geojson' 

# 创建一个GeoJSON图层,用于曼尼普尔邦的边界,并将其添加到地图上 

folium.GeoJson(manipur_geojson, 

               style_function=lambda feature: { 

                   'fillColor': 'white', 

                   'color': 'black', 

                   'weight': 2, 

                   'fillOpacity': 1 

               }).add_to(map) 


# 为不同的年份定义颜色调色板 

color_palette = {2022: 'red', 2023: 'blue'} 

# 基于年份将事件用不同的颜色绘制在地图上 

for index, row in df_filtered22_23.iterrows(): 

    folium.CircleMarker([row['latitude'], row['longitude']], 

                        radius=3, 

                        color=color_palette[row['year']], 

                        fill=True, 

                        fill_color=color_palette[row['year']], 

                        fill_opacity=0.5).add_to(map) 

# 添加地图特性 

folium.TileLayer('cartodbpositron').add_to(map) 

# 设置地图的中心和缩放级别 

map.fit_bounds(map.get_bounds()) 

map.get_root().html.add_child(folium.Element(legend_html)) 

# 显示地图 

map

输出:

可以看到,中央山谷地区观察到了更高的事件密集度。这可能是由于各种因素,如人口密度、基础设施、可访问性和历史社会政治动态等。中央山谷地区更加人口密集和经济发达,可能会比山区发生更多事件和事件。

ACLED事件类型

ACLED事件类型是指ACLED数据集中记录的不同类型事件的分类。这些事件类型捕捉到与冲突、暴力、抗议和其他感兴趣事件相关的各种活动和事件。ACLED数据集中的一些事件类型包括针对平民的暴力、爆炸/远程暴力、抗议、骚乱等等。这些事件类型提供了有关ACLED数据库中记录的冲突和相关事件的性质和动态的见解。

下面的代码生成了一个条形图,按年份分组显示了印度曼尼普尔邦的事件类型。

import pandas as pd 

import matplotlib.pyplot as plt 

df_filteredevent = df_filtered.copy() 

df_filteredevent['event_date'] = pd.to_datetime(df_filteredevent['event_date']) 

# Group the data by year 

df_cross_event = df_filteredevent.groupby(df_filteredevent['event_date'].dt.year)
['event_type'].value_counts().unstack() 

# Define the color palette 

color_palette = ['#FF5C5C', '#FFC94C', '#FF9633', '#8E8EE1', '#72C472', '#0818A8'] 

# Plot the bar chart 

fig, ax = plt.subplots(figsize=(10, 6)) 

df_cross_event.plot.bar(ax=ax, color=color_palette) 

# Set the x-axis tick labels to display only the year 

ax.set_xticklabels(df_cross_event.index, rotation=0) 

# Set the legend 

ax.legend(title='事件类型', bbox_to_anchor=(1, 1.02), loc='upper left') 

# Set the axis labels and title 

ax.set_xlabel('年份') 

ax.set_ylabel('事件数量') 

ax.set_title('曼尼普尔邦:ACLED事件类型按年份分组显示')  

# Adjust the padding and layout 

plt.tight_layout(rect=[0, 0, 0.95, 1])   

# Display the plot 

plt.show()

输出:

ACLED事件类型按年份分组显示

值得注意的是,事件类型的条形图可突出显示“抗议”类别的支配地位,这可能掩盖相对差异,使其他事件类型的比较变得具有挑战性。通过排除或分离“抗议”类别,可调整可视化效果,从而更清晰地比较其他事件类型。

下面的代码段从数据中过滤出“抗议”事件类型。然后按年份将其余事件分组,并在条形图中将其可视化,排除了支配性的“抗议”类别。结果可视化提供了更清晰的事件类型按年份显示。

import pandas as pd 

import matplotlib.pyplot as plt 


df_filteredevent = df_filtered.copy() 

df_filteredevent['event_date'] = pd.to_datetime(df_filteredevent['event_date']) 


# Filter out the "Protests" event type 

df_filteredevent = df_filteredevent[df_filteredevent['event_type'] != '抗议'] 


# Group the data by year 

df_cross_event = df_filteredevent.groupby(df_filteredevent['event_date'].dt.year)
['event_type'].value_counts().unstack() 


# Define the color palette 

color_palette = ['#FF5C5C', '#FFC94C', '#FF9633', '#8E8EE1', '#72C472', '#0818A8'] 


# Plot the bar chart 

fig, ax = plt.subplots(figsize=(10, 6)) 

df_cross_event.plot.bar(ax=ax, color=color_palette) 


# Set the x-axis tick labels to display only the year 

ax.set_xticklabels(df_cross_event.index, rotation=0) 


# Set the legend 

ax.legend(title='事件类型', bbox_to_anchor=(1, 1.02), loc='upper left') 


# Set the axis labels and title 

ax.set_xlabel('年份') 

ax.set_ylabel('事件数量') 

ax.set_title('曼尼普尔邦:ACLED事件类型(不包括抗议)按年份分组显示') 


# Adjust the padding and layout 

plt.tight_layout(rect=[0, 0, 0.95, 1]) 


# Display the plot 

plt.show()

输出:

ACLED事件类型按年份分组显示(不包括抗议)

可视化事件动态:映射事件类型和频率

我们使用交互式地图,根据事件类型和频率在地图上绘制具有不同标记大小和颜色的事件。它代表了不同事件的空间分布和强度,允许快速识别模式、热点和趋势。这种方法增强了事件的地理动态,促进了数据驱动的决策,使得对已识别的模式和频率进行有效的资源分配和有针对性的干预成为可能。

事件被绘制为圆形标记,颜色和大小根据事件类型和频率而异。

import folium 

import json 


# 为2023年筛选数据 

df_filtered23 = df_filtered[df_filtered['year'] == 2023] 


# 计算每个位置的事件计数 

event_counts = df_filtered23.groupby(['latitude', 'longitude']).size().
reset_index(name='count') 


# 创建地图实例 

map = folium.Map(location=[24.8170, 93.9368], zoom_start=8) 


# 从GeoJSON文件中加载Manipu边界 

with open('Manipur.geojson') as f: 

    manipur_geojson = json.load(f) 


# 为Manipu边界创建GeoJSON图层并将其添加到地图中 

folium.GeoJson(manipur_geojson, 

               style_function=lambda feature: { 

                   'fillColor': 'white', 

                   'color': 'black', 

                   'weight': 2, 

                   'fillOpacity': 1 

               }).add_to(map) 


# 定义受ACLED主题类别启发的自定义颜色调色板 

event_type_palette = { 

    '针对平民的暴力': '#FF5C5C',       # 深橙色 

    '爆炸/远程暴力': '#FFC94C',       # 明黄色 

    '战略发展': '#FF9633',            # 浅橙色 

    '战斗': '#8E8EE1',               # 紫色 

    '抗议': '#72C472',              # 绿色 

    '骚乱': '#0818A8'                # 紫蓝色 

} 

# 根据事件类型和频率,在地图上绘制具有不同标记大小和颜色的事件 

for index, row in event_counts.iterrows(): 

    location = (row['latitude'], row['longitude']) 

    count = row['count'] 


    # 获取当前位置的事件类型 

    event_type = df_filtered23[(df_filtered23['latitude'] == row['latitude']) & 

                             (df_filtered23['longitude'] == row['longitude'])]
                             ['event_type'].values[0] 


    folium.CircleMarker( 

        location=location, 

        radius=2 + count * 0.1, 

        color=event_type_palette[event_type], 

        fill=True, 

        fill_color=event_type_palette[event_type], 

        fill_opacity=0.7 

    ).add_to(map) 


# 为2023年添加图例 

legend_html = """ 

<div style="position: fixed; bottom: 50px; right: 50px; z-index: 1000; font-size: 14px; 

             background-color: rgba(255, 255, 255, 0.8); padding: 10px; border-radius: 
             5px;"> 

    <p><strong>图例</strong></p> 

    <p><span style="color: #FF5C5C;">针对平民的暴力</span></p> 

    <p><span style="color: #FFC94C;">爆炸/远程暴力</span></p> 

    <p><span style="color: #FF9633;">战略发展</span></p> 

    <p><span style="color: #8E8EE1;">战斗</span></p> 

    <p><span style="color: #72C472;">抗议</span></p> 

    <p><span style="color: #0818A8;">骚乱</span></p> 

</div> 

""" 

map.get_root().html.add_child(folium.Element(legend_html)) 



# 显示地图 

map 

输出:

冲突的主要参与者

在这一步中,我们了解有关缅甸冲突或事件中涉及的不同实体或组织的见解。在ACLED数据集中,“actor1”指代记录事件中涉及的主要参与者。它代表着发起或参与特定冲突或事件的主要实体或组织。 “Actor1”列提供有关主要参与者的身份信息,例如政府、反叛组织、民族武装或其他参与冲突或事件的实体。 “actor1”列中的每个唯一值都代表涉及记录事件的不同参与者或组。

然后使用以下代码片段可视化“actor1”的值计数:

这段代码基于“actor1”列的值计数过滤数据框,仅选择计数大于或等于5的数据。然后可视化结果数据。

import matplotlib.pyplot as plt 

# 基于值计数过滤数据框 >= 5 
filtered_df = df_filtered[(df_filtered['year'] != 2023)]['actor1'].
value_counts().loc[lambda x: x >= 5] 

# 创建水平条形图的图形和轴 
fig, ax = plt.subplots(figsize=(8, 6)) 

# 定义颜色调色板 
color_palette = ['#FF5C5C', '#FFC94C', '#FF9633', '#8E8EE1', '#72C472', '#0818A8'] 

# 绘制水平条形图 
filtered_df.plot.barh(ax=ax, color=color_palette) 

# 添加标签和标题 
ax.set_xlabel('计数') 
ax.set_ylabel('Actor1') 
ax.set_title('Actor1的值计数 (>= 5) (2016年1月至2022年12月9日)', 
pad=55) 

# 设置数据可用性信息 
data_info = "于2023年6月17日获取" 

# 添加信用和数据可用性信息 
plt.text(0.5, 1.1, "数据来源:", ha='center', transform=ax.transAxes, 
fontsize=10) 
plt.text(0.5, 1.05, "武装冲突地点与事件数据项目(ACLED); www.acleddata.com", 
         ha='center', transform=ax.transAxes, fontsize=10) 
plt.text(0.5, 1.0, data_info, ha='center', transform=ax.transAxes, fontsize=10) 

# 在每个条形图旁显示计数 
for i, v in enumerate(filtered_df.values): 
    ax.text(v + 3, i, str(v), color='black') 

# 显示图形 
plt.tight_layout() 
plt.show() 

输出:

Actor1的值计数

图表代表从2016年1月至2022年12月9日的数据。此外,“计数大于或等于5”的条件意味着仅包括在分析中并在图表中显示出现频率大于或等于5的实体。

如下代码片段所示,使用以下可视化方法比较2022年和2023年之间的类别计数。

import matplotlib.pyplot as plt 
import numpy as np 

# 过滤2022年的数据框 
filtered_df_2022 = df_filtered[df_filtered['year'] == 2022]['actor1'].
value_counts().loc[lambda x: x >= 10] 

# 过滤2023年的数据框 
filtered_df_2023 = df_filtered[df_filtered['year'] == 2023]['actor1'].
value_counts().loc[lambda x: x >= 10] 

# 获取在任一数据框中出现超过10次的唯一类别 
categories = set(filtered_df_2022.index).union(set(filtered_df_2023.index)) 

# 创建字典以存储类别计数 
category_counts = {'2022': [], '2023': []} 

# 遍历类别 
for category in categories: 
    # 如果可用,则添加2022年的计数,否则添加0 
    category_counts['2022'].append(filtered_df_2022.get(category, 0)) 
    # 如果可用,则添加2023年的计数,否则添加0 
    category_counts['2023'].append(filtered_df_2023.get(category, 0)) 

# 排除计数为0的类别 
non_zero_categories = [category for category, count_2022, count_2023 in zip
(categories, category_counts['2022'], category_counts['2023']) if count_2022 > 
0 or count_2023 > 0] 

# 创建柱状图的图形和轴 
fig, ax = plt.subplots(figsize=(10, 6)) 

# 设置x轴位置 
x = np.arange(len(non_zero_categories)) 

# 设置条形图的宽度 
width = 0.35 

# 绘制2022年的条形图 
bars_2022 = ax.bar(x - width/2, category_counts['2022'], width, color=color_palette[0],
 label='2022') 

# 绘制2023年的条形图 
bars_2023 = ax.bar(x + width/2, category_counts['2023'], width, color=color_palette[1],
 label='2023') 

# 设置x轴刻度标签并旋转以提高可见性 
ax.set_xticks(x) 
ax.set_xticklabels(non_zero_categories, rotation=90) 

# 设置y轴标签 
ax.set_ylabel('计数') 

# 设置标题和图例 
ax.set_title('Actor1类别的比较 (>= 10) - 2022 vs 2023') 
ax.legend() 

# 在每个条形图上方添加计数值 
for rect in bars_2022 + bars_2023: 
    height = rect.get_height() 
    ax.annotate(f'{height}', xy=(rect.get_x() + rect.get_width() / 2, height), 
                xytext=(0, 3), textcoords="offset points", ha='center', va='bottom') 

# 调整行间距 
plt.subplots_adjust(top=0.9) 

# 显示图形 
plt.show()

输出:

以下代码片段可获取2022年和2023年6月9日之前的Manipur ACLED数据的比较:

import matplotlib.pyplot as plt 

import numpy as np 


# 为2022年过滤数据帧 

filtered_df_2022 = df_filtered[df_filtered['year'] == 2022]['actor1'].
value_counts().loc[lambda x: x >= 10] 


# 为2023年过滤数据帧 

filtered_df_2023 = df_filtered[df_filtered['year'] == 2023]['actor1'].
value_counts().loc[lambda x: x >= 10] 


# 获取在任一数据帧中出现超过10次的唯一类别 

categories = set(filtered_df_2022.index).union(set(filtered_df_2023.index)) 


# 创建一个字典来存储类别计数 

category_counts = {'2022': [], '2023': []} 


# 遍历类别 

for category in categories: 

    # 如果有2022年的计数,则添加,否则添加0 

    category_counts['2022'].append(filtered_df_2022.get(category, 0)) 


    # 如果有2023年的计数,则添加,否则添加0 

    category_counts['2023'].append(filtered_df_2023.get(category, 0)) 


# 排除计数为0的类别 

non_zero_categories = [category for category, count_2022, count_2023 in 
zip(categories, category_counts['2022'], category_counts['2023']) 
if count_2022 > 0 or count_2023 > 0] 


# 为条形图创建图形和轴 

fig, ax = plt.subplots(figsize=(10, 6)) 


# 设置x轴位置 

x = np.arange(len(non_zero_categories)) 


# 设置条形的宽度 

width = 0.35 


# 画2022年的条形图 

bars_2022 = ax.bar(x - width/2, category_counts['2022'], width, 
color=color_palette[0], label='2022') 


# 画2023年的条形图 

bars_2023 = ax.bar(x + width/2, category_counts['2023'], width, 
color=color_palette[1], label='2023') 


# 设置x轴刻度标签并旋转它们以便更好地显示 

ax.set_xticks(x) 

ax.set_xticklabels(non_zero_categories, rotation=90) 


# 设置y轴标签 

ax.set_ylabel('计数') 


# 设置标题和图例 

ax.set_title('Actor1类别(>= 10)的比较 - 2022 vs 2023') 

ax.legend() 


# 在每个条形上方添加计数值 

for rect in bars_2022 + bars_2023: 

    height = rect.get_height() 

    ax.annotate(f'{height}', xy=(rect.get_x() + rect.get_width() / 2, height), 

                xytext=(0, 3), textcoords="offset points", ha='center', va='bottom') 


# 显示图表 

plt.show() 

输出:

冲突强度分析

下面的代码片段通过将“event_date”列转换为日期时间来准备数据以进行进一步的分析或可视化。执行交叉制表,重构数据帧以便于更容易地解释和使用。它使用pd.crosstab()函数在“df_filtered”中的“event_date”(使用dt.to_period(‘m’)转换为月度期间)和“inter1”列之间创建交叉制表(频率表)。稍后,将“df_filtered”按“event_date”分组,并计算每个日期的“fatalities”的总和。计算并添加每个月的死亡人数到现有的交叉制表数据帧中,结果为“df_conflicts”。它包括类别事件数据和相应的死亡信息以进行进一步分析。

代码实现

import pandas as pd 

# 将“event_date”列转换为日期时间数据类型 

df_filtered['event_date'] = pd.to_datetime(df_filtered['event_date']) 



# 执行交叉制表操作 

df_cross = pd.crosstab(df_filtered['event_date'].dt.to_period('m'), 
df_filtered['inter1']) 



# 重命名列 

df_cross.columns = ['国家武装部队', '叛军组织', '政治民兵', 
'身份民兵', '暴民', '抗议者', '平民', '外部/其他部队'] 



# 将期间索引转换为日期 

df_cross['event_date'] = df_cross.index.to_timestamp() 



# 重置索引 

df_cross.reset_index(drop=True, inplace=True) 

df2 = df_filtered.copy() 

df2['event_date'] = pd.to_datetime(df2['event_date']) 



fatality_filtered = (df2 

.filter(['event_date','fatalities']) 

.groupby(['event_date']) 

.fatalities 

.sum() 

) 

df_fatality_filtered = fatality_filtered.to_frame().reset_index() 

df_fatality_month= df_fatality_filtered.resample('M', on="event_date").sum() 

df_fatality_month = df_fatality_month.reset_index() 

df_fatalities = df_fatality_month.drop(columns=['event_date']) 

df_concat = pd.concat([df_cross, df_fatalities], axis=1) 

df_conflicts = df_concat.copy() 

输出:

该代码可视化了按参与方类型分类的曼尼普尔州每月事件的冲突强度分析,以报告的死亡人数为权重。线条的宽度基于每种参与方类型的死亡人数。这种分析使我们能够识别模式和不同参与方类型的相对影响。为冲突研究提供有价值的见解,以进行进一步的分析和决策。

import plotly.graph_objects as go 

fig = go.Figure() 

fig.add_trace(go.Scatter( 

    name='国家军队', 

    x=df_conflicts['event_date'].dt.strftime('%Y-%m'), 

    y=df_conflicts['国家军队'], 

    mode='markers+lines', 

    marker=dict(color='darkviolet', size=4), 

    showlegend=True 

)) 



fig.add_trace(go.Scatter( 

    name='死亡人数权重', 

    x=df_conflicts['event_date'], 

    y=df_conflicts['国家军队']+df_conflicts['fatalities']/5, 

    mode='lines', 

    marker=dict(color="#444"), 

    line=dict(width=1), 

    hoverinfo='skip', 

    showlegend=False 

))



fig.add_trace(go.Scatter( 

    name='死亡人数权重', 

    x=df_conflicts['event_date'], 

    y=df_conflicts['国家军队']-df_conflicts['fatalities']/5, 

    marker=dict(color="#444"), 

    line=dict(width=1), 

    mode='lines', 

    fillcolor='rgba(68, 68, 68, 0.3)', 

    fill='tonexty', 

    hoverinfo='text', 

    hovertemplate='<br>%{x|%b\n%Y}<br><i>死亡人数: %{text}</i>', 

    text=['{}'.format(i) for i in df_conflicts['fatalities']], 

    showlegend=False 

)) 



#在此处插入其他事件类型的add_trace....



fig.update_xaxes( 

    dtick="M3",  # 将刻度频率设置为3个月(季度) 

    tickformat="%b\n%Y" 

) 



fig.update_layout( 

    yaxis_title='事件数', 

    title={ 

        'text': '冲突强度分析:按参与方类型分类的曼尼普尔州事件,以报告的死亡人数为权重', 

        'y': 0.95, 

        'x': 0.5, 

        'xanchor': 'center', 

        'yanchor': 'top', 

        'font': {'size': 20} 

    }, 

    annotations=[ 

        dict( 

            text="2016年1月到2023年6月9日|数据来源:武装冲突地点和事件数据项目(ACLED),www.acleddata.com", 

            xref="paper", 

            yref="paper", 

            x=0.5, 

            y=1.06, 

            showarrow=False, 

            font={'size': 12} 

        ) 

    ], 

    hovermode="x", 

    xaxis=dict( 

        showgrid=False 

    ), 

    yaxis=dict( 

        showgrid=False 

    ) 

) 


fig.data[0].marker.size = 4 

fig.data[3].marker.size = 4 

fig.data[6].marker.size = 4 

fig.data[9].marker.size = 4 

fig.data[12].marker.size = 4 

fig.data[15].marker.size = 4 

fig.data[18].marker.size = 4 

fig.data[21].marker.size = 4 



fig.show()

输出:

多线图中某个变量值(在本例中为“抗议者”)较其他变量值高。这可能会扭曲感知,使准确比较和解释不同变量的趋势变得困难。一个变量的主导地位会减弱,因为评估其他变量之间的相对变化和关系变得具有挑战性。可视化可能会受到压缩或混乱的视觉效果的影响,较小价值变量的细节丧失,以及可能会偏向解释的不平衡强调。

为了减轻这些缺点并清晰地可视化最近的冲突强度,过滤了2023年和2022年的冲突事件数据,以下是输出:

将日期设置为冲突趋势分析的指数,使用日常数据获取以下数据框进行进一步分析。

滚动平均和冲突趋势分析

在冲突趋势分析中,30天和7天的滚动窗口是常见的。它们用于计算冲突相关数据在特定时间段内的滚动平均值或平均数。

滚动窗口指沿时间线移动的固定大小时间间隔,包括该间隔内的指定数量的数据点。例如,在30天滚动窗口中,该间隔包括当前日期和前29天。在7天滚动窗口中,该间隔包括当前日期和前6天,表示一周的数据量。

移动平均值是通过取窗口内数据点的平均值来计算的。它提供了数据的平滑表示,减少了短期波动并突出了长期趋势。

通过计算冲突分析中的30天和7天滚动平均值,分析人员可以获得关于冲突事件的总体模式和趋势的见解。它可以识别出长期趋势,同时捕捉数据中的短期波动。这些滚动平均值可以帮助揭示潜在模式,并提供更清晰的冲突动态演变图像。

代码片段

以下代码片段创建每个冲突场景的图表。

import matplotlib.pyplot as plt 

import pandas as pd 



# Variables to calculate rolling means for 

variables = ['State Forces', 'Rebel Groups', 'Political Militias', 
'Identity Militias', 'Rioters', 'Protesters', 
'Civilians', 'External/Other Forces'] 



# Calculate rolling means for each variable 

data_7d_rol = {} 

data_30d_rol = {} 

for variable in variables: 

    data_7d_rol[variable] = data_ts[variable].rolling(window=7, min_periods=1).mean() 

    data_30d_rol[variable] = data_ts[variable].rolling(window=30, min_periods=1).mean() 




# Plotting separate graphs for each variable 

for variable in variables: 

    fig, ax = plt.subplots(figsize=(11, 4)) 



    # Plotting 7-day rolling mean 

    ax.plot(data_ts.index, data_7d_rol[variable], linewidth=2, label='7-d Rolling Mean') 



    # Plotting 30-day rolling mean 

    ax.plot(data_ts.index, data_30d_rol[variable], color='0.2', linewidth=3, 
    label='30-d Rolling Mean') 



    # Beautification of plot 

    ax.legend() 

    ax.set_xlabel('Year') 

    ax.set_ylabel('Events accounted by ' + variable) 

    ax.set_title('Trends in ' + variable + ' Conflicts') 



    # Add main heading and subheading 

    fig.suptitle(main_title, fontsize=14, fontweight='bold', y=1.05) 

    #ax.text(0.5, -0.25, sub_title, transform=ax.transAxes, fontsize=10, color='red', ha='center') 

    ax.text(0.5, 0.95, sub_title, transform=ax.transAxes, fontsize=10, color='red', ha='center') 



    plt.tight_layout() 

    plt.show() 

输出:

State Forces
Rebel Groups
政治民兵
身份民兵
暴徒
抗议者
平民
外部/其他势力

注意:本博客生成的图表和数据分析仅用于演示数据科学技术的应用。这些分析并没有从根本上得出关于冲突复杂动态的明确结论或解释。在接近冲突分析时应谨慎,认识到冲突的多方面性以及需要综合和针对特定情况的理解,这超出了本分析的范围。

结论

本博客使用 ACLED 数据分析探究了印度曼尼普尔地区的冲突事件和模式。使用交互式地图和其他可视化工具来查看曼尼普尔地区的 ACLED 事件。分析曼尼普尔地区的事件类型揭示了与冲突、暴力、抗议和其他感兴趣事件有关的各种活动和事件。为了了解冲突事件的趋势,我们计算了 30 天和 7 天的滚动均值。这些滚动均值提供了数据的平滑表示,减少了短期波动并突出了长期趋势。总体而言,这些发现可能有助于更好地了解该地区的冲突动态,并支持进一步的研究和决策过程。

关键点

  1. 交互式 ACLED 数据分析:深入了解真实世界的冲突数据并获取见解。
  2. 交互式地图可视化冲突的时空动态。
  3. 强调可视化和数据分析对有效理解的重要性。
  4. 确定主要参与者揭示了塑造冲突格局的关键实体。
  5. 滚动均值计算揭示了冲突中的短期波动和长期趋势。

希望您觉得本文有用。请随时在 LinkedIn 上联系我。让我们共同努力,利用数据促进积极变革。

常见问题

参考文献

1. Raleigh, Clionadh, Andrew Linke, Håvard Hegre and Joakim Karlsen. (2010). “IntroducingACLED-Armed Conflict Location and Event Data.” Journal of Peace Research 47(5) 651-660.

2. ACLED. (2023). “Armed Conflict Location & Event Data Project (ACLED)Codebook, 2023.

本文所示媒体不归 Analytics Vidhya 所有,仅由作者自行决定使用。