【Python】实现对LGBT+ rights worldwide (2025)数据集的可视化展示

发布于:2025-06-28 ⋅ 阅读:(14) ⋅ 点赞:(0)

我用夸克网盘分享了「lgbtq_rights_by_country数据集」,点击链接即可保存。
链接:https://pan.quark.cn/s/aa0fa91491e8

摘要: 本文运用Python编程实现对LGBTQ+权利相关数据的处理与可视化展示。通过直方图与地图两种可视化方式,分别从分类统计和地理分布角度呈现全球不同国家LGBTQ+权利的认可情况。

关键词:LGBTQ+权利;可视化;直方图;地理地图;数据处理

一、有关数据集:全球LGBT+权利(2025)数据集

kaggle源地址:https://www.kaggle.com/datasets/wilomentena/lgbt-rights-worldwide
有如下列数据:

  • 同性性行为
  • 承认同性婚姻
  • 同性婚姻
  • 同性伴侣收养
  • 允许LGB人士公开在军队服役
  • 反歧视法律涉及性取向
  • 性别认同/表达相关法律

在这里插入图片描述

二、LGBTQ+权利数据的直方图可视化

2.1 数据准备

  1. 数据加载:利用pandas库的read_csv函数,从指定路径'E:\\pycharm_workspace\\数据集\\lgbtq_rights_by_country.csv'读取LGBTQ+权利相关数据,代码如下:
import pandas as pd
file_path = 'E:\\pycharm_workspace\\数据集\\lgbtq_rights_by_country.csv'
data = pd.read_csv(file_path)
  1. 数据预处理:为更清晰表示分类数据,将除'Territory'列外的其他列数据类型转换为分类类型,具体代码如下:
columns_to_convert = data.columns[1:]
for col in columns_to_convert:
    data[col] = data[col].astype('category')

2.2 直方图绘制

  1. 创建可视化布局:使用matplotlib库创建一个大小为(15, 20)的图形,并采用4行2列的子图布局,为每个问题绘制单独的条形图。
import matplotlib.pyplot as plt
import seaborn as sns
plt.figure(figsize=(15, 20))
for i, column in enumerate(columns_to_convert, 1):
    plt.subplot(4, 2, i)
  1. 计算与绘制条形图:对每列数据计算每个类别的计数,并使用seaborn库的barplot函数绘制条形图,同时避免弃用警告,代码如下:
counts = data[column].value_counts().sort_index()
sns.barplot(x=counts.index, y=counts.values, hue=counts.index, palette='viridis', legend=False)
  1. 设置图表属性:为每个子图设置标题、坐标轴标签,并在柱子上方显示具体数值,增强图表可读性。
plt.title(f'{column} 分布', fontsize=14)
plt.xlabel('类别', fontsize=12)
plt.ylabel('国家/地区数量', fontsize=12)
for j, v in enumerate(counts.values):
    plt.text(j, v + 0.5, str(v), ha='center')
  1. 整体图表设置:使用tight_layout函数优化子图布局,设置整个图表的总标题,并显示图表。
plt.tight_layout()
plt.suptitle('全球LGBT+权利法律认可情况分布', y=1.02, fontsize=16)
plt.show()

在这里插入图片描述

整体代码:

import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd

# 设置中文字体支持(如果需要显示中文)
plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号

# ================== 直方图绘制 ==================
# 1. 加载数据
file_path = 'D:\\pyprogect\\图形页面编程\\lgbtq_rights_by_country\\lgbtq_rights_by_country.csv'
data = pd.read_csv(file_path)

# 2. 数据预处理:将所有列转换为分类类型
columns_to_convert = data.columns[1:]  # 排除'Territory'列
for col in columns_to_convert:
    data[col] = data[col].astype('category')

# 3. 创建可视化
plt.figure(figsize=(14, 12))  # 增加高度以提供更多垂直空间

# 改为 5 行 2 列布局,避免拥挤
for i, column in enumerate(columns_to_convert, 1):
    plt.subplot(5, 2, i)  # 更宽松的布局

    counts = data[column].value_counts().sort_index()
    sns.barplot(x=counts.index, y=counts.values, hue=counts.index, palette='viridis', legend=False)

    plt.title(f'{column}', fontsize=10)  # 更小的标题字体
    plt.xlabel('')
    plt.ylabel('国家/地区数量', fontsize=9)
    plt.xticks(rotation=45, fontsize=8)  # 缩小刻度字体

    # 柱子上方数值更小字体
    for j, v in enumerate(counts.values):
        plt.text(j, v + 0.5, str(v), ha='center', fontsize=7)

# 自动调整子图布局
plt.tight_layout()

# 手动增加顶部和垂直间距
plt.subplots_adjust(top=0.92, hspace=0.8)  # 增大 hspace 来拉开子图间距

# 添加总标题
plt.suptitle('全球LGBT+权利法律认可情况分布', y=0.97, fontsize=14)
plt.show()

三、LGBTQ+权利数据的地图可视化

3.1 数据准备

  1. 加载世界地图数据:通过geopandas库的read_file函数,读取世界地图数据文件"E:\\pycharm_workspace\\ne_110m_admin_0_countries.shp",代码如下:
import geopandas as gpd
world = gpd.read_file("E:\\pycharm_workspace\\数据集\\ne_110m_admin_0_countries.shp")

在这里插入图片描述

  1. 加载LGBTQ+权利数据:再次从指定路径读取LGBTQ+权利数据文件"E:\\pycharm_workspace\\数据集\\lgbtq_rights_by_country.csv",代码如下:
lgbtq_df = pd.read_csv("E:\\pycharm_workspace\\数据集\\lgbtq_rights_by_country.csv")
  1. 数据转换为数值评分:定义calculate_score函数,将LGBTQ+权利数据中的分类数据转换为数值评分。遍历特定的权利相关列,根据列值'Yes''No''Unknown'分别赋予1、 - 1和0的分数,并累加到每行对应的评分中,最后将评分结果添加到lgbtq_df数据集中。
def calculate_score(row):
    score = 0
    for column in ['Same-sex sexual activity', 'Recognition of same-sex unions', 'Same-sex marriage',
                  'Adoption by same-sex couples', 'LGBT people allowed to serve openly in military?',
                  'Anti-discrimination laws concerning sexual orientation', 'Laws concerning gender identity/expression']:
        if row[column] == 'Yes':
            score += 1
        elif row[column] == 'No':
            score += -1
        else:  # Unknown
            score += 0
    return score
lgbtq_df['Score'] = lgbtq_df.apply(calculate_score, axis=1)
  1. 数据合并:使用pandasmerge函数,根据world数据集中的NAME列和lgbtq_df数据集中的Territory列进行左连接合并,确保所有国家在地图数据中有对应的LGBTQ+权利评分,并对可能存在的缺失评分填充为0。
merged = world.merge(lgbtq_df, left_on="NAME", right_on="Territory", how="left")
merged["Score"] = merged["Score"].fillna(0)

3.2 地图绘制

  1. 创建地图对象:借助matplotlibcartopy库,创建一个带有ccrs.PlateCarree()投影的GeoAxes对象,并设置背景颜色。
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
fig, ax = plt.subplots(figsize=(14, 8), subplot_kw={'projection': ccrs.PlateCarree()})
ax.set_facecolor("#f0f0f0")
  1. 绘制基础地图:绘制世界地图作为基础底图,设置地图颜色为白色,边界颜色为"#444",线宽为0.5。
world.plot(ax=ax, color="white", edgecolor="#444", linewidth=0.5, transform=ccrs.PlateCarree())
  1. 设置颜色映射与归一化:选择"RdBu_r"颜色映射,设定评分的最小值vmin为 - 7,最大值vmax为7,并创建归一化对象norm
from matplotlib.colors import Normalize
from matplotlib.cm import get_cmap
cmap = get_cmap("RdBu_r")
vmin, vmax = -7, 7
norm = Normalize(vmin=vmin, vmax=vmax)
  1. 绘制带有分数的地图:根据合并数据集中的Score列绘制地图,设置线条宽度、边界颜色等参数,并处理缺失值的显示。
merged.plot(
    column="Score",
    cmap=cmap,
    norm=norm,
    linewidth=0.8,
    ax=ax,
    edgecolor="#aaaaaa",
    missing_kwds={"color": "lightgray"},
    transform=ccrs.PlateCarree()
)
  1. 添加颜色条与标注:添加颜色条以说明评分与颜色的对应关系,并设置其标签。同时设置地图的标题、坐标轴标签。(原代码中对高分和低分国家标注部分被注释,如需使用,可取消注释。)
cbar = plt.colorbar(
    plt.cm.ScalarMappable(norm=norm, cmap=cmap),
    ax=ax,
    orientation="vertical",
    shrink=0.6,
    pad=0.05,
    label="LGBTQ+ Rights Score\n(7 = All Yes, -7 = All Unknown/No)"
)
plt.title("Global LGBTQ+ Rights Distribution", fontsize=16, pad=20)
plt.xlabel("Longitude", fontsize=12)
plt.ylabel("Latitude", fontsize=12)
  1. 添加网格线并保存显示:添加网格线,并设置其属性,如是否显示标签、线条颜色、样式等。使用tight_layout函数优化布局,将绘制好的地图保存为"lgbtq_rights_world_map.png"文件,并显示地图。
gl = ax.gridlines(
    crs=ccrs.PlateCarree(),
    draw_labels=True,
    linewidth=0.5,
    color="gray",
    alpha=0.5,
    linestyle="--"
)
gl.top_labels = False
gl.right_labels = False
gl.xlabel_style = {"size": 10, "color": "gray"}
gl.ylabel_style = {"size": 10, "color": "gray"}
plt.tight_layout()
plt.savefig("lgbtq_rights_world_map.png", dpi=300, bbox_inches="tight")
plt.show()

在这里插入图片描述

完整代码

import matplotlib.pyplot as plt
import geopandas as gpd
import pandas as pd
import numpy as np
from matplotlib.colors import Normalize
from matplotlib.cm import get_cmap
import cartopy.crs as ccrs

# 1. 加载世界地图数据
world = gpd.read_file("D:\\pyprogect\\图形页面编程\\lgbtq_rights_by_country\\ne_110m_admin_0_countries\\ne_110m_admin_0_countries.shp")

# 2. 加载LGBTQ+权利数据
lgbtq_df = pd.read_csv("D:\\pyprogect\\图形页面编程\\lgbtq_rights_by_country\\lgbtq_rights_by_country.csv")

# 3. 将分类数据转换为数值评分
def calculate_score(row):
    score = 0
    for column in ['Same-sex sexual activity', 'Recognition of same-sex unions', 'Same-sex marriage',
                  'Adoption by same-sex couples', 'LGBT people allowed to serve openly in military?',
                  'Anti-discrimination laws concerning sexual orientation', 'Laws concerning gender identity/expression']:
        if row[column] == 'Yes':
            score += 1
        elif row[column] == 'No':
            score += -1
        else:  # Unknown
            score += 0
    return score

lgbtq_df['Score'] = lgbtq_df.apply(calculate_score, axis=1)


# 4. 合并数据
merged = world.merge(lgbtq_df, left_on="NAME", right_on="Territory", how="left")
merged["Score"] = merged["Score"].fillna(0)

# 5. 绘制地图
# 使用 cartopy 创建 GeoAxes 对象
fig, ax = plt.subplots(figsize=(14, 8), subplot_kw={'projection': ccrs.PlateCarree()})
ax.set_facecolor("#f0f0f0")

# 先绘制基础地图
world.plot(ax=ax, color="white", edgecolor="#444", linewidth=0.5, transform=ccrs.PlateCarree())

cmap = get_cmap("RdBu_r")
vmin, vmax = -7, 7
norm = Normalize(vmin=vmin, vmax=vmax)

# 绘制带有分数的地图
merged.plot(
    column="Score",
    cmap=cmap,
    norm=norm,
    linewidth=0.8,
    ax=ax,
    edgecolor="#aaaaaa",
    missing_kwds={"color": "lightgray"},
    transform=ccrs.PlateCarree()
)

# 添加颜色条
cbar = plt.colorbar(
    plt.cm.ScalarMappable(norm=norm, cmap=cmap),
    ax=ax,
    orientation="vertical",
    shrink=0.6,
    pad=0.05,
    label="LGBTQ+ Rights Score\n(7 = All Yes, -7 = All Unknown/No)"
)

plt.title("Global LGBTQ+ Rights Distribution", fontsize=16, pad=20)
plt.xlabel("Longitude", fontsize=12)
plt.ylabel("Latitude", fontsize=12)

# # 标注高分和低分国家
# highlight_countries = merged[merged['Score'].isin([-7, 7, -6, 6, -5, 5])][['NAME', 'Score', 'Territory']]
# for _, row in highlight_countries.iterrows():
#     try:
#         geom = merged[merged["NAME"] == row['NAME']]["geometry"].values[0]
#         x, y = geom.centroid.x, geom.centroid.y
#         plt.annotate(
#             f"{row['Territory']} ({row['Score']})",
#             xy=(x, y),
#             xytext=(5, 5),
#             textcoords="offset points",
#             ha="left",
#             va="center",
#             fontsize=10,
#             color="black" if row['Score'] < 0 else "white",
#             weight="bold"
#         )
#     except IndexError:
#         pass

# 添加网格线
gl = ax.gridlines(
    crs=ccrs.PlateCarree(),
    draw_labels=True,
    linewidth=0.5,
    color="gray",
    alpha=0.5,
    linestyle="--"
)
gl.top_labels = False
gl.right_labels = False
gl.xlabel_style = {"size": 10, "color": "gray"}
gl.ylabel_style = {"size": 10, "color": "gray"}

plt.tight_layout()
plt.savefig("lgbtq_rights_world_map.png", dpi=300, bbox_inches="tight")
plt.show()

四、结论

通过直方图和地图两种可视化方式,呈现了全球LGBTQ+权利的状况。直方图从各个权利维度展示了不同认可类别的国家数量分布,地图则从地理空间上展示了综合评分的分布情况。