随机性

在前面的章节中,我们发展了进行深刻数据描述所需的技能。数据科学家还必须能够理解随机性。例如,他们必须能够将个体随机分配到治疗组和对照组,然后尝试判断两组结果中观察到的任何差异仅仅是由于随机分配还是真正由于治疗。

在本章中,我们开始分析随机性。首先,我们将使用 Python 进行随机选择。在 numpy 中有一个名为 random 的子模块,其中包含许多涉及随机选择的函数。其中一个函数叫做 choice。它从数组中随机选择一个项,并且选择任何项的概率相等。函数调用为 np.random.choice(array_name),其中 array_name 是要进行选择的数组的名称。

因此,以下代码以 50% 的概率求值为 treatment,以 50% 的概率求值为 control

[In ]:
from datascience import *
path_data = '../../../assets/data/'
import numpy as np

import matplotlib
matplotlib.use('Agg')
%matplotlib inline
import matplotlib.pyplot as plots
plots.style.use('fivethirtyeight')
[In ]:
two_groups = make_array('treatment', 'control')
np.random.choice(two_groups)
'treatment'

上述代码与我们迄今为止运行的所有其他代码之间的最大区别在于,上述代码并不总是返回相同的值。它可能返回 treatmentcontrol,我们无法提前知道它会选择哪一个。我们可以通过提供第二个参数(即重复该过程的次数)来重复这个过程。

[In ]:
np.random.choice(two_groups, 10)
array(['control', 'control', 'treatment', 'treatment', 'control',
       'control', 'control', 'control', 'control', 'control'], dtype='<U9')

关于随机事件的一个基本问题是它们是否发生。例如:

  • 个体是否被分配到治疗组?
  • 赌徒是否会赢钱?
  • 民调是否做出了准确的预测?

一旦事件发生了,你可以对所有这些问题回答“是”或“否”。在编程中,通常的做法是通过将语句标记为 True 或 False 来实现。例如,如果个体确实被分配到了治疗组,那么语句“该个体被分配到了治疗组”将为 True。如果不是,则为 False

布尔值与比较

在 Python 中,布尔值以逻辑学家 George Boole 的名字命名,表示真值,只取两个可能的值:TrueFalse。无论问题是否涉及随机性,布尔值最常来源于比较运算符。Python 包含多种比较值的运算符。例如,3 大于 1 + 1

[In ]:
3 > 1 + 1
True

True 表示比较有效;Python 已确认了这个关于 31+1 之间关系的简单事实。常用比较运算符的完整集合如下所列。

比较 运算符 True 示例 False 示例
小于 < 2 < 3 2 < 2
大于 > 3 > 2 3 > 3
小于或等于 <= 2 <= 2 3 <= 2
大于或等于 >= 3 >= 3 2 >= 3
等于 == 3 == 3 3 == 2
不等于 != 3 != 2 2 != 2

注意在判断相等性的比较中使用了两个等号 ==。这是必要的,因为 Python 已经使用 = 来表示赋值到一个名称,正如我们所见。它不能使用相同的符号用于不同的目的。因此,如果你想检查 5 是否等于 10/2,你需要小心:5 = 10/2 会返回错误消息,因为 Python 假设你正在尝试将表达式 10/2 的值赋给名为数字 5 的名称。相反,你必须使用 5 == 10/2,它求值为 True

[In ]:
5 = 10/2
SyntaxError: can't assign to literal (<ipython-input-5-e8c755f5e450>, line 1)
  File "<ipython-input-5-e8c755f5e450>", line 1
    5 = 10/2
            ^
SyntaxError: can't assign to literal
[In ]:
5 == 10/2
True

一个表达式可以包含多个比较,并且为了使整个表达式为 True,所有比较都必须成立。例如,我们可以使用以下表达式来表示 1+113 之间。

[In ]:
1 < 1 + 1 < 3
True

两个数的平均值总是在较小的数和较大的数之间。我们在下面用数字 xy 表示这种关系。你可以尝试不同的 xy 值来确认这种关系。

[In ]:
x = 12
y = 5
min(x, y) <= (x+y)/2 <= max(x, y)
True

比较字符串

字符串也可以进行比较,它们的顺序是字母顺序。较短的字符串小于以该较短字符串开头的较长字符串。

[In ]:
'Dog' > 'Catastrophe' > 'Cat'
True

让我们回到随机选择。回忆数组 two_groups 仅包含两个元素,treatmentcontrol。要查看随机分配的个体是否去了治疗组,你可以使用比较:

[In ]:
np.random.choice(two_groups) == 'treatment'
True

和之前一样,随机选择并不总是相同的,因此比较的结果也不总是相同的。这将取决于选择了 treatment 还是 control。对于任何涉及随机选择的单元格,最好多次运行该单元格以了解结果的波动性。

比较数组和值

回忆一下,我们可以同时对数组中的许多数字进行算术运算。例如,make_array(0, 5, 2)*2 等价于 make_array(0, 10, 4)。类似地,如果我们比较一个数组和一个值,数组的每个元素都与该值进行比较,比较结果求值为一个布尔值数组。

[In ]:
tosses = make_array('Tails', 'Heads', 'Tails', 'Heads', 'Heads')
tosses == 'Heads'
array([False,  True, False,  True,  True])

NumPy 方法 count_nonzero 求值为数组中非零(即 True)元素的数量。

[In ]:
np.count_nonzero(tosses == 'Heads')
3