跳转到内容

快速入门指南

恭喜您成功安装了Sequenzo! 🎉 现在就可以开始玩转社会序列分析啦。

这个指南会手把手教你分析国家级CO₂排放序列。想了解我们是怎么把原始数据处理成适合做序列分析的格式?详细过程看这里(TODO:SequenzoWebsite网页)。

python新手?没关系!Sequenzo专门为小白设计,界面直观好上手,不管你是编程萌新还是Python老司机,都能快速掌握。

这个教程结束后,你将掌握:

  1. 安装Sequenzo
  2. 导入和对数据进行初步探索
  3. 分析社会序列
  4. 结果可视化

好了,开始我们的数据分析之旅吧!🐍✨

1. 初步了解数据

python
# 导入必要的库
# 你的调用代码(比如在脚本或notebook中)

from sequenzo import * # 导入包,给它一个简短的别名
import pandas as pd # 数据处理

# 列出Sequenzo中所有可用的数据集
# 现在用别名来调用函数:
print('Sequenzo中的可用数据集: ', list_datasets())

# 加载我们在本教程中要探索的数据
# `df`是`dataframe`的缩写,这是数据集的常用变量名
# df = load_dataset('country_co2_emissions')
df = load_dataset('country_co2_emissions_global_deciles')

# 显示数据框
df
Sequenzo中的可用数据集:  ['biofam', 'biofam_child_domain', 'biofam_left_domain', 'biofam_married_domain', 'chinese_colonial_territories', 'country_co2_emissions', 'country_co2_emissions_global_deciles', 'country_co2_emissions_global_quintiles', 'country_co2_emissions_local_deciles', 'country_co2_emissions_local_quintiles', 'country_gdp_per_capita', 'polyadic_samplec1', 'polyadic_samplep1', 'polyadic_seqc1', 'polyadic_seqp1']
country180018011802180318041805180618071808...2013201420152016201720182019202020212022
0AfghanistanD1 (Very Low)D1 (Very Low)D1 (Very Low)D1 (Very Low)D1 (Very Low)D1 (Very Low)D1 (Very Low)D1 (Very Low)D1 (Very Low)...D7D7D7D7D7D7D7D7D7D7
1AlbaniaD1 (Very Low)D1 (Very Low)D1 (Very Low)D1 (Very Low)D1 (Very Low)D1 (Very Low)D1 (Very Low)D1 (Very Low)D1 (Very Low)...D9D9D9D9D9D9D9D9D9D9
2AlgeriaD1 (Very Low)D1 (Very Low)D1 (Very Low)D1 (Very Low)D1 (Very Low)D1 (Very Low)D1 (Very Low)D1 (Very Low)D1 (Very Low)...D9D9D9D9D9D9D9D9D9D9
3AndorraD7D7D7D7D7D7D7D7D7...D10 (Very High)D10 (Very High)D10 (Very High)D10 (Very High)D10 (Very High)D10 (Very High)D10 (Very High)D10 (Very High)D10 (Very High)D10 (Very High)
4AngolaD3D3D3D3D3D3D3D3D3...D8D8D8D8D8D8D8D8D8D8
..................................................................
189VenezuelaD1 (Very Low)D1 (Very Low)D1 (Very Low)D1 (Very Low)D1 (Very Low)D1 (Very Low)D1 (Very Low)D1 (Very Low)D1 (Very Low)...D9D9D9D9D9D8D6D8D8D8
190VietnamD3D3D3D3D3D3D3D3D3...D8D8D8D8D8D9D9D9D9D9
191YemenD1 (Very Low)D1 (Very Low)D1 (Very Low)D1 (Very Low)D1 (Very Low)D1 (Very Low)D1 (Very Low)D1 (Very Low)D1 (Very Low)...D8D8D7D7D7D7D7D7D7D7
192ZambiaD7D7D7D7D7D7D7D7D7...D7D7D7D7D7D7D7D7D7D7
193ZimbabweD5D5D5D5D5D5D5D5D5...D8D8D8D8D8D8D8D8D8D8

194 rows × 224 columns

这个分类基于所有年份的人均CO₂排放值:

  • 极低(后20%)
  • 低(20-40%)
  • 中等(40-60%)
  • 高(60-80%)
  • 极高(前20%)

用社会序列分析的术语来说,每个类别叫做一个状态,状态的序列叫做社会序列。总的来说,这个数据集展示了每个国家每年的人均CO₂排放水平。

以安道尔为例:

python
# 筛选安道尔的数据
andorra_df = df[df['country'] == 'Andorra']

# 显示安道尔的数据框
andorra_df
country180018011802180318041805180618071808...2013201420152016201720182019202020212022
3AndorraD7D7D7D7D7D7D7D7D7...D10 (Very High)D10 (Very High)D10 (Very High)D10 (Very High)D10 (Very High)D10 (Very High)D10 (Very High)D10 (Very High)D10 (Very High)D10 (Very High)

1 rows × 224 columns

根据结果(原数据集的一个子集),我们可以看到安道尔的人均CO₂排放在这些年里经历了以下变化:

  • 1990-1991: 从"极高"水平开始,说明排放量在所有国家中排前20%
  • 1992-1997: 下降到"高"水平(60-80百分位)
  • 1998: 短暂回到"极高"水平
  • 2000年代至今: 稳定在"高"水平(60-80百分位),并一直保持到2019年

但这就带来了一个问题:如果我们想分析所有国家的序列怎么办? 🤔

这时候Sequenzo就能派上用场!

2. 使用 Sequenzo 分析社会序列

python
# 创建 SequenceData 对象

# 定义时间跨度变量
time_list = list(df.columns)[1:]

# states = ['Very Low', 'Low', 'Middle', 'High', 'Very High']
states = ['D1 (Very Low)', 'D10 (Very High)', 'D2', 'D3', 'D4', 'D5', 'D6', 'D7', 'D8', 'D9']

# TODO: 编写异常处理逻辑:如果参数不存在,则提示传入正确的参数
# sequence_data = SequenceData(df, time=time, id_col="country", ids=df['country'].values, states=states)

sequence_data = SequenceData(df,
                             time=time_list,
                             id_col="country",
                             states=states,
                             labels=states)

sequence_data
[!] Detected missing values (empty cells) in the sequence data.
    → Automatically added 'Missing' to `states` and `labels` for compatibility.
    However, it's strongly recommended to manually include it when defining `states` and `labels`.
    For example:

        states = ['At Home', 'Left Home', 'Missing']
        labels = ['At Home', 'Left Home', 'Missing']

    This ensures consistent color mapping and avoids unexpected visualization errors.

[>] SequenceData initialized successfully! Here's a summary:
[>] Number of sequences: 194
[>] Number of time points: 223
[>] Min/Max sequence length: 216 / 223
[>] There are 7 missing values across 1 sequences.
    First few missing sequence IDs: ['Panama'] ...
[>] Top sequences with the most missing time points:
    (Each row shows a sequence ID and its number of missing values)

             Missing Count
Sequence ID               
Panama                   7
[>] States: ['D1 (Very Low)', 'D10 (Very High)', 'D2', 'D3', 'D4', 'D5', 'D6', 'D7', 'D8', 'D9', 'Missing']
[>] Labels: ['D1 (Very Low)', 'D10 (Very High)', 'D2', 'D3', 'D4', 'D5', 'D6', 'D7', 'D8', 'D9', 'Missing']





SequenceData(194 sequences, States: ['D1 (Very Low)', 'D10 (Very High)', 'D2', 'D3', 'D4', 'D5', 'D6', 'D7', 'D8', 'D9', 'Missing'])

数据可视化

在众多可视化方法中,索引图是最常用的。下面我们来看看它的效果。

我们刚才已经成功创建了SequenceData对象,这是Sequenzo分析社会序列的核心工具。

如果只用肉眼看原始数据,我们一次只能关注一个国家的发展轨迹。但有了Sequenzo,我们就能同时分析所有国家的数据!可视化是其中最关键的功能,它能帮我们发现数据中隐藏的规律和趋势。

python
# 绘制索引图
# TODO: 在这里同样处理意外参数的问题。TypeError: plot_sequence_index() 函数收到了意外的关键字参数 'sortv'

plot_sequence_index(sequence_data,
                    # save_as='index_plot'
                    )

png

<Figure size 640x480 with 0 Axes>

还想挖掘更多信息?状态分布图来啦!

python
sequence_data.plot_legend(save_as="legend_plot")

png

python
plot_most_frequent_sequences(sequence_data, save_as='test', top_n=5)hh

png

<Figure size 640x480 with 0 Axes>
python
plot_mean_time(sequence_data, save_as='mean_time')

png

<Figure size 640x480 with 0 Axes>
python
plot_transition_matrix(sequence_data, save_as='transition_matrix')

png

<Figure size 640x480 with 0 Axes>
python
plot_state_distribution(sequence_data, save_as='state_distribution')

png

<Figure size 640x480 with 0 Axes>
python
plot_modal_state(sequence_data, save_as='modal_state')

png

差异性度量

python
# 参数替换选项:用"OM/DHD/HAM"代替"OMspell",用"CONSTANT"代替"TRATE"
om = get_distance_matrix(seqdata=sequence_data,
                         method='OM',
                         sm="TRATE",
                         indel="auto")
om
[>] Processing 194 sequences with 11 unique states.
[>] Transition-based substitution-cost matrix (TRATE) initiated...
  - Computing transition probabilities for: [D1 (Very Low), D10 (Very High), D2, D3, D4, D5, D6, D7, D8, D9, Missing]
[>] Indel cost generated.

[>] Identified 194 unique sequences.
[>] Starting Optimal Matching(OM)...
[>] Computing all pairwise distances...
[>] Computed Successfully.
AfghanistanAlbaniaAlgeriaAndorraAngolaAntigua and BarbudaArgentinaArmeniaAustraliaAustria...UgandaUkraineUruguayUzbekistanVanuatuVenezuelaVietnamYemenZambiaZimbabwe
Afghanistan0.000000272.363879141.530885405.839693357.116339352.452702369.202821199.747566363.605396367.308098...356.188303251.681276391.564474253.570661333.417093193.512323339.495876337.004372405.784131389.419165
Albania272.3638790.000000196.640891293.042386360.848766357.623372291.258820190.293293330.065835318.787795...301.974406207.816080269.205424205.916577385.871215217.202167355.905637150.343476331.733788324.072412
Algeria141.530885196.6408910.000000299.876169360.346243329.826237297.445339131.698913285.521108291.201892...386.745755173.060640276.896587145.923477361.33798575.716405348.517376309.997189397.970384368.047516
Andorra405.839693293.042386299.8761690.000000356.053656317.797407119.351333288.455080161.034886143.550606...442.272407231.894801323.007193256.673631337.870059320.299300305.637267338.668802248.972441316.165089
Angola357.116339360.848766360.346243356.0536560.000000291.024809338.252215304.404207333.524614343.035738...299.756320323.190476213.309453329.042700223.247060388.304116126.257652324.332208355.987397347.278292
..................................................................
Venezuela193.512323217.20216775.716405320.299300388.304116332.208197314.154419167.770756307.697612294.576219...407.898441178.451252299.052292159.381580393.4631820.000000386.746863338.328445409.781349363.126942
Vietnam339.495876355.905637348.517376305.637267126.257652277.169745281.862722262.901696284.480681296.840967...250.273278313.199712224.199999317.111338171.558720386.7468630.000000332.362799311.052135313.268987
Yemen337.004372150.343476309.997189338.668802324.332208402.822666338.626193287.908848368.726059362.779293...210.976531287.655467289.098219284.491015338.798635338.328445332.3627990.000000323.373702353.783341
Zambia405.784131331.733788397.970384248.972441355.987397400.131845247.433419362.309280364.953012359.363387...442.218057373.720811406.480220371.778073255.268940409.781349311.052135323.3737020.000000304.666582
Zimbabwe389.419165324.072412368.047516316.165089347.278292279.071995315.245317292.686113257.977877282.863190...372.870754325.264179340.907764320.059748347.484712363.126942313.268987353.783341304.6665820.000000

194 rows × 194 columns

python
plot_relative_frequency(seqdata=sequence_data,
                        distance_matrix=om,
                        num_groups=12,
                        dpi=200,
                        # save_as='relative_frequency_plot'
                        )

# 可视化主要问题
# 1. 当把横坐标从“严格的分类标签”变成“数值(年份/年龄)”时,刻度有可能跑偏,得手动把 xticks/布局调回来。
# 2. 状态(分类)多了以后,默认 legend 效果会很糟,得自己选位置或分列、扩增画布空间,才能让图例和主体同时都好看、好读。

png

<Figure size 640x480 with 0 Axes>

聚类分析

python
cluster = Cluster(om, sequence_data.ids, clustering_method='ward')
cluster.plot_dendrogram(xlabel="Countries", ylabel="Distance")
[>] Converting DataFrame to NumPy array...

png

<Figure size 640x480 with 0 Axes>
python
# Create a ClusterQuality object to evaluate clustering quality创建一个 ClusterQuality 对象,用于评估聚类质量。
cluster_quality = ClusterQuality(cluster)
cluster_quality.compute_cluster_quality_scores()
cluster_quality.plot_combined_scores(norm='zscore', save_as='combined_scores')
summary_table = cluster_quality.get_metrics_table()
print(summary_table)

png

  Metric  Opt. Clusters  Opt. Value  Z-Score Norm.  Min-Max Norm.
0    ASW              6    1.922696       1.922696            1.0
1   ASWw              6    1.922696       1.922696            1.0
2     HG              2    3.235991       3.235991            1.0
3    PBC             20    1.028963       1.028963            1.0
4     CH              8    0.613044       0.613044            1.0
5     R2             20    1.297366       1.297366            1.0
6     HC             20    1.228937       1.228937            1.0



<Figure size 640x480 with 0 Axes>
python
cluster_results = ClusterResults(cluster)
membership_table = cluster_results.get_cluster_memberships(num_clusters=5)
print(membership_table)
distribution = cluster_results.get_cluster_distribution(num_clusters=5)
print(distribution)
cluster_results.plot_cluster_distribution(num_clusters=5, save_as="distribution.png", title=None)
       Entity ID  Cluster
0    Afghanistan        1
1        Albania        1
2        Algeria        1
3        Andorra        3
4         Angola        4
..           ...      ...
189    Venezuela        1
190      Vietnam        4
191        Yemen        2
192       Zambia        3
193     Zimbabwe        5

[194 rows x 2 columns]
   Cluster  Count  Percentage
0        1     55       28.35
1        2     30       15.46
2        3     49       25.26
3        4     18        9.28
4        5     42       21.65


/Users/lei/Documents/Sequenzo_all_folders/Sequenzo-main/sequenzo/clustering/hierarchical_clustering.py:598: FutureWarning: 

Passing `palette` without assigning `hue` is deprecated and will be removed in v0.14.0. Assign the `x` variable to `hue` and set `legend=False` for the same effect.

  ax = sns.barplot(x='Cluster', y='Count', data=distribution, palette='pastel')

png

<Figure size 640x480 with 0 Axes>
python
mapping_dict = {
    1: 'xxx',
    2: 'Test',
    3: 'The name of the cluster',
    4: 'xxxxx',
    5: 'whsiaa',
}

membership_table = replace_cluster_id_by_labels(membership_table,
                                                mapping=mapping_dict,
                                                new_cluster_column_name='Cluster',
                                                new_id_column_name='ID')

membership_table
IDCluster
0Afghanistanxxx
1Albaniaxxx
2Algeriaxxx
3AndorraThe name of the cluster
4Angolaxxxxx
.........
189Venezuelaxxx
190Vietnamxxxxx
191YemenTest
192ZambiaThe name of the cluster
193Zimbabwewhsiaa

194 rows × 2 columns

python
plot_sequence_index(seqdata=sequence_data,
                    id_group_df=membership_table,
                    categories='Cluster',
                    # save_as='cluster_index_plot'
                    )

png

python
plot_state_distribution(seqdata=sequence_data,
                            id_group_df=membership_table,
                            categories='Cluster',
                            # save_as='cluster_state_distribution_plot'
                        )

png

Regression

python
python

Conclusions

python

Released under the BSD-3-Clause License.