示例:性别比例

在本节中,我们将继续使用上一节中的 us_pop 表格。但这次我们将关注与 SEX 列相关的人口趋势。

[In ]:
from datascience import *
import numpy as np
path_data = '../../../assets/data/'
import matplotlib
matplotlib.use('Agg')
%matplotlib inline
import matplotlib.pyplot as plots
plots.style.use('fivethirtyeight')
[In ]:
# As of August 2021, this census file is online here: 
data = 'http://www2.census.gov/programs-surveys/popest/technical-documentation/file-layouts/2010-2019/nc-est2019-agesex-res.csv'

# A local copy can be accessed here in case census.gov moves the file:
# data = path_data + 'nc-est2019-agesex-res.csv'

full_census_table = Table.read_table(data)
#full_census_table

partial_census_table = full_census_table.select('SEX', 'AGE', 'POPESTIMATE2014', 'POPESTIMATE2019')
#partial_census_table

us_pop = partial_census_table.relabeled('POPESTIMATE2014', '2014').relabeled('POPESTIMATE2019', '2019')
[In ]:
us_pop
SEX  | AGE  | 2014    | 2019
0    | 0    | 3954787 | 3783052
0    | 1    | 3948891 | 3829599
0    | 2    | 3958711 | 3922044
0    | 3    | 4005928 | 3998665
0    | 4    | 4004032 | 4043323
0    | 5    | 4004576 | 4028281
0    | 6    | 4133372 | 4017227
0    | 7    | 4152666 | 4022319
0    | 8    | 4118349 | 4066194
0    | 9    | 4106068 | 4061874
... (296 rows omitted)

SEX 列中使用的代码

AGE20142019 列的内容易于理解。AGE 列包含以完成年数计算的年龄。特殊值 999 表示所有年龄的总人口,100 表示 “100 岁及以上”。20142019 列包含这两年中每年美国人口的估计值。

然而,SEX 列更难解释。

人口普查表要求受访者通过勾选标有“男性”和“女性”的两个框之一来提供每个家庭成员性别。SEX 列包含数字代码:1 表示男性,2 表示女性,0 表示总计。

自 1790 年以来,这个问题基本上以相同的方式被询问。但自那时起,关于人类性别是否适合简单的二元分类,已有相当多的研究。例如,非二元性别的人并不认同自己 exclusively 是男性或女性。加州大学洛杉矶分校法学院威廉姆斯研究所 2021 年的一项研究估计,美国至少有 120 万人认同为非二元性别。

通过继续使用历史上形成的问题形式,人口普查未能反映性别分类的复杂性。2020 年人口普查提供的并在下方引文中复制的解释,并未包含对自我认同不属于男性或女性的人的说明。

回答性别问题很简单。

自 1790 年首次人口普查以来,一直包含关于性别的问题。所有涉及个人特征的 2020 年人口普查问题都基于自我认同。当你完成人口普查时,选择你认同的生理性别的框。……

在接下来的内容中,我们将在记住上述问题的前提下使用人口普查提供的数据。我们将使用术语 “男性” 指代在人口普查表上选择了 “男性”(SEX 代码 1)的人。我们将使用 “女性” 指代选择了 “女性”(SEX 代码 2)的人。

总体比例

现在我们将开始查看 2019 年的性别比例。首先,让我们一起来看所有年龄组。记住这意味着查看 “年龄” 编码为 999 的行。表格 all_ages 包含这些信息。有三行:一行是总人口,一行是男性,一行是女性。

[In ]:
us_pop_2019 = us_pop.drop('2014')
all_ages = us_pop_2019.where('AGE', are.equal_to(999))
all_ages
SEX  | AGE  | 2019
0    | 999  | 328239523
1    | 999  | 161657324
2    | 999  | 166582199

all_ages 的第 0 行包含这两年中每年的美国总人口。美国在 2019 年约有 3.3 亿人。

第 1 行包含男性人数,第 2 行包含女性人数。比较这两行可以看出,2019 年美国女性人数多于男性。

第 1 行和第 2 行的人口数加起来等于第 0 行的总人口。

为了与其他数值具有可比性,我们需要将这些计数转换为占总人口的百分比。让我们获取 2019 年的总数并为之命名。然后,我们将显示一个带有比例列的人口表格。与我们之前的观察一致,女性多于男性,2019 年人口的 50.75% 是女性,约 49.25% 是男性。

[In ]:
pop_2019 = all_ages.column('2019').item(0)
all_ages.with_column(
    'Proportion', all_ages.column('2019')/pop_2019
).set_format('Proportion', PercentFormatter)
SEX  | AGE  | 2019      | Proportion
0    | 999  | 328239523 | 100.00%
1    | 999  | 161657324 | 49.25%
2    | 999  | 166582199 | 50.75%

婴儿中的比例

然而,当我们观察婴儿时,情况正好相反。我们将婴儿定义为未满一岁的婴儿,对应 AGE 为 0 的行。以下是他们在人口中的数量。你可以看到男婴数量多于女婴。

[In ]:
infants = us_pop_2019.where('AGE', are.equal_to(0))
infants
SEX  | AGE  | 2019
0    | 0    | 3783052
1    | 0    | 1935117
2    | 0    | 1847935

和之前一样,我们可以将这些计数转换为占总婴儿数的百分比。结果表格显示,2019 年,美国略高于 51% 的婴儿是男性。

[In ]:
infants_2019 = infants.column('2019').item(0)
infants.with_column(
    'Proportion', infants.column('2019')/infants_2019
).set_format('Proportion', PercentFormatter)
SEX  | AGE  | 2019    | Proportion
0    | 0    | 3783052 | 100.00%
1    | 0    | 1935117 | 51.15%
2    | 0    | 1847935 | 48.85%

事实上,长期以来人们观察到新生儿中男性的比例略高于 1/2。其原因尚未被完全理解,科学家仍在研究

各年龄段的性别比例

我们已经看到,虽然男婴多于女婴,但总体人口中女性多于男性。这意味着性别比例必然在不同的年龄段有所不同。

为了研究这种变化,我们将分离出女性和男性的数据,并消除所有年龄汇总且 AGE 编码为 999 的行。

表格 femalesmales 包含两个性别代码各自的数据。

[In ]:
females_all_rows = us_pop_2019.where('SEX', are.equal_to(2))
females = females_all_rows.where('AGE', are.not_equal_to(999))
females
SEX  | AGE  | 2019
2    | 0    | 1847935
2    | 1    | 1871014
2    | 2    | 1916500
2    | 3    | 1955655
2    | 4    | 1976372
2    | 5    | 1967081
2    | 6    | 1964271
2    | 7    | 1966584
2    | 8    | 1986471
2    | 9    | 1988726
... (91 rows omitted)
[In ]:
males_all_rows = us_pop_2019.where('SEX', are.equal_to(1))
males = males_all_rows.where('AGE', are.not_equal_to(999))
males
SEX  | AGE  | 2019
1    | 0    | 1935117
1    | 1    | 1958585
1    | 2    | 2005544
1    | 3    | 2043010
1    | 4    | 2066951
1    | 5    | 2061200
1    | 6    | 2052956
1    | 7    | 2055735
1    | 8    | 2079723
1    | 9    | 2073148
... (91 rows omitted)

现在的计划是比较这两年每年每个年龄段的女性人数和男性人数。数组和 Table 方法给了我们直接的方法来实现这一点。这两个表每个年龄段都有一行。

[In ]:
males.column('AGE')
array([  0,   1,   2,   3,   4,   5,   6,   7,   8,   9,  10,  11,  12,
        13,  14,  15,  16,  17,  18,  19,  20,  21,  22,  23,  24,  25,
        26,  27,  28,  29,  30,  31,  32,  33,  34,  35,  36,  37,  38,
        39,  40,  41,  42,  43,  44,  45,  46,  47,  48,  49,  50,  51,
        52,  53,  54,  55,  56,  57,  58,  59,  60,  61,  62,  63,  64,
        65,  66,  67,  68,  69,  70,  71,  72,  73,  74,  75,  76,  77,
        78,  79,  80,  81,  82,  83,  84,  85,  86,  87,  88,  89,  90,
        91,  92,  93,  94,  95,  96,  97,  98,  99, 100])
[In ]:
females.column('AGE')
array([  0,   1,   2,   3,   4,   5,   6,   7,   8,   9,  10,  11,  12,
        13,  14,  15,  16,  17,  18,  19,  20,  21,  22,  23,  24,  25,
        26,  27,  28,  29,  30,  31,  32,  33,  34,  35,  36,  37,  38,
        39,  40,  41,  42,  43,  44,  45,  46,  47,  48,  49,  50,  51,
        52,  53,  54,  55,  56,  57,  58,  59,  60,  61,  62,  63,  64,
        65,  66,  67,  68,  69,  70,  71,  72,  73,  74,  75,  76,  77,
        78,  79,  80,  81,  82,  83,  84,  85,  86,  87,  88,  89,  90,
        91,  92,  93,  94,  95,  96,  97,  98,  99, 100])

对于任何给定的年龄,我们可以通过将女性人数除以男性人数来获得女性对男性的性别比例。

要一步完成此操作,我们可以使用 column 提取女性计数的数组和相应的男性计数数组,然后简单地将一个数组除以另一个数组。逐元素除法将创建一个所有年份的性别比例数组。

[In ]:
ratios = Table().with_columns(
    'AGE', females.column('AGE'),
    '2019 F:M RATIO', females.column('2019')/males.column('2019')
)
ratios
AGE  | 2019 F:M RATIO
0    | 0.954947
1    | 0.955289
2    | 0.955601
3    | 0.957242
4    | 0.956177
5    | 0.954338
6    | 0.956801
7    | 0.956633
8    | 0.955161
9    | 0.959278
... (91 rows omitted)

从显示中可以看出,九岁及以下儿童的比例都在 0.96 左右。当女性对男性比例小于 1 时,女性人数少于男性。因此我们看到,在 0、1、2 一直到 9 的每个年龄组中,女孩都少于男孩。更准确地说,在每个这样的年龄组中,每 100 个男孩大约对应 96 个女孩。

那么,女性在总人口中的比例怎么会高于男性呢?

当我们检查年龄段的高端时,情况完全不同。以下是 75 岁以上人群的女性对男性比例。

[In ]:
ratios.where('AGE', are.above(75)).show()
<IPython.core.display.HTML object>

不仅所有这些比例都大于 1(表明所有这些年龄组中女性多于男性),而且其中许多比例远大于 1。

  • 在 92 岁和 93 岁,比例接近 2,意味着在 2019 年这些年龄的女性大约是男性的两倍。
  • 在 99 岁,女性大约是男性的三倍。

如果你想知道在这些高龄有多少人,你可以使用 Python 来查找:

[In ]:
males.where('AGE', are.contained_in(make_array(92, 93, 99)))
SEX  | AGE  | 2019
1    | 92   | 131684
1    | 93   | 103415
1    | 99   | 14596
[In ]:
females.where('AGE', are.contained_in(make_array(92, 93, 99)))
SEX  | AGE  | 2019
2    | 92   | 262383
2    | 93   | 217370
2    | 99   | 42528

下面的图表显示了按年龄绘制的性别比例。蓝色曲线显示了 2019 年各年龄段的性别比例。

从 0 到 60 岁,比例几乎为 1(表明男女人数接近相等)。但从 65 到 70 岁左右开始,比例急剧上升(女性多于男性)。

美国女性人数超过男性,部分原因是老年人中明显偏向女性的不平衡。

[In ]:
ratios.plot('AGE')
A line graph with 'AGE' on the x-axis ranging from 0 to 100 and '2019 F:M RATIO' on the y-axis labeled from 1.0 to 3.0. The line stays around/below 1.0 until age 40. From Age 40 to 8, the ratio increases slowly up to about 1.25. After 80, the ratio increases exponentially up to 3.0 and above.