table {
border-collapse: collapse;
width: 100%;
margin-bottom: 1rem;
}
th, td {
border: 1px solid #ddd;
padding: 8px;
text-align: left;
}
th {
background-color: #f2f2f2;
}
tr:nth-child(even) {
background-color: #f9f9f9;
}
pre {
background-color: #f8f8f8;
padding: 15px;
border-radius: 4px;
overflow-x: auto;
}
1、在Jupyter中编辑模式(Edit mode)和命令模式(Command mode)有什么区别?
编辑模式与命令模式
编辑模式
在编辑模式下,JupyterLab 的行为与普通文本编辑器类似,支持以下常见键盘快捷键:
Shift + 方向键
:选择文本
Ctrl + c
:复制
Ctrl + x
:剪切
Ctrl + v
:粘贴
Ctrl + z
:撤销
Ctrl + ]
:缩进
Ctrl + [
:取消缩进
Ctrl + /
:切换注释
命令模式
通过按下
ESC
键可进入命令模式,此时可使用以下操作:
使用
上下箭头键
在代码单元格之间移动
按
d, d
(连续按两次 d)删除当前选中的单元格
按
z
撤销上一次操作
按
a
和
b
分别在当前单元格的
上方
和
下方
插入一个新的空白单元格
通过简单的
拖放操作
重新定位单元格
模式切换
ESC
:从编辑模式进入命令模式
Enter
:从命令模式进入编辑模式
2、常见的标量类型有哪些?
常见的标量类型有:
bool
(逻辑类型)、
int
(整数类型)、
float
(浮点类型)、
complex
(复数类型)、
str
(字符串类型)。
3、说出常见的顺序对象有哪些
常见的顺序对象有:
列表(lists)
元组(tuples)
范围(ranges)
字符串(strings)
4、是否每个可迭代对象都是序列对象?
不是。存在很多其他可迭代类型,它们是非序列的,不能使用索引运算符随机访问它们的元素,所以并非每个可迭代对象都是序列对象。
5、dict是否是顺序类型的实例?
不是,字典不是顺序类型的对象。例如:
x[0]
在字典
x
中是无效的,会引发错误,因为字典不能通过索引(位置)来访问元素。不像列表、元组、范围和字符串等顺序类型可以通过索引访问数据项。
6、给定一个由数值标量组成的列表x,我们如何创建一个长度相同的新列表,该列表包含原列表中所有元素的平方?
在Python中,可以使用列表推导式来实现。以下是示例代码:
x = [1, 2, 3, 4, 5]
new_list = [i**2 for i in x]
print(new_list)
在上述代码中,通过
[i**2 for i in x]
这个列表推导式,遍历列表
x
中的每个元素
i
,并将其平方后添加到新列表中。运行代码后,新列表将包含原列表中所有元素的平方。
7、如何进行对象复制,以及何时应该进行对象复制?
对于可变类型的对象,可以使用其自带的相关方法进行复制,例如列表可以使用
copy()
方法。如:
x = [1, 2, 3]
y = x.copy()
这样
y
就是
x
的一个副本。
当我们不希望对一个对象的修改影响到另一个引用该对象的变量时,就应该进行对象复制。例如在代码中,若:
y = x
由于赋值运算符不会创建
x
的副本,
x
和
y
引用计算机内存中的同一个对象,对
x
的修改会影响到
y
;而使用:
y = x.copy()
复制后,对
x
的修改就不会影响到
y
。
8、numpy.arange和numpy.linspace有什么区别?
np.r_[0:10:2]
类似于
np.arange(0, 10, 2)
,生成的是从 0 开始,以步长 2 递增,到小于 10 的整数序列,即
array([0, 2, 4, 6, 8])
;而
np.r_[0:1:5j]
类似于
np.linspace(0, 1, 5)
,这里的
5j
指定了要生成序列的输出长度,生成的是在 0 到 1 之间均匀分布的 5 个值的序列,即
array([0., 0.25, 0.5, 0.75, 1.])
。可以看出,
numpy.arange
是按照指定的起始值、步长来生成序列;而
numpy.linspace
是按照指定的起始值、结束值以及要生成的元素数量来生成均匀分布的序列。
9、当我们使用astype方法将逻辑向量转换为数值向量时会发生什么?当我们将数值向量转换为逻辑向量时又会怎样?
当使用
astype
方法将逻辑向量转换为数值向量时,
False
会变成
0
,
True
会变成
1
。
例如:
np.array([True, False, True, True, False]).astype(int)
会得到:
array([1, 0, 1, 1, 0])
当将数值向量转换为逻辑向量时,
0
会被转换为
False
,其他任何值(包括
-0.326
等)都会被转换为
True
。
例如:
np.array([-2, -0.326, -0.000001, 0.0, 0.1, 1, 7643]).astype(bool)
会得到:
array([ True, True, True, False, True, True, True])
也可以使用以下方式得到相同结果:
np.array([-2, -0.326, -0.000001, 0.0, 0.1, 1, 7643]) != 0
10、什么是钟形分布?
钟形分布具有以下特点:
分布围绕某个值呈现出良好的对称性,例如身高数据集的分布围绕约160cm对称;
最典型(正常、常见)的观测值位于中间位置,并且概率质量在两侧迅速减小。
例如身高数据集的经验分布就是很好的钟形,该数据集可以用正态分布很好地拟合。
11、在比较男性和女性的身高时,我们如何解释算术平均值、中位数、标准差、四分位距和偏度这些可能不同的值?
在比较男性和女性的身高时,不同统计量的解释如下:
算术平均值
:它代表了一组身高数据的平均水平。如果男性身高的算术平均值高于女性,说明总体上男性的身高更高。例如,男性平均身高可能为175cm,女性平均身高为162cm,这直观地体现了两者在平均身高上的差异。
中位数
:将身高数据按从小到大排序后位于中间位置的数值。它不受极端值的影响,能反映数据的中间水平。若男性身高的中位数大于女性,意味着一半男性的身高高于女性的中位数身高,同样表明男性身高整体较高。
标准差
:量化了身高数据围绕算术平均值的典型离散程度。如果男性身高的标准差较大,说明男性身高的个体差异更明显,可能既有身高较矮的男性,也有身高很高的男性;而女性身高标准差较小,则表示女性身高相对较为集中在平均值附近。例如,男性身高标准差为7cm,女性为5cm,这显示男性身高的分布更分散。
四分位距
:是第75百分位数与第25百分位数的差值,代表了中间50%最典型身高值的范围。它是一种稳健的统计量,不受最小25%和最大25%观测值的影响。若男性身高的四分位距大于女性,说明男性身高在中间50%的范围内差异更大。
偏度
:衡量身高数据分布的不对称程度。对于对称分布,偏度近似为零。如果男性身高偏度接近零,说明男性身高分布较为对称;若女性身高存在正偏度,意味着女性身高分布有较重的右尾,即有较多较高身高的女性拉高了分布的右侧;负偏度则表示有较重的左尾,即有较多较矮身高的女性。例如,男性身高偏度为0.05,女性身高偏度为0.2,说明女性身高分布相对男性更偏向右侧。
12、List the four general ways to index a vector.
四种常见的向量索引方式
向量的索引一般有以下四种方式:
基于切片的索引
基于切片的索引可以根据切片选择向量中的一部分元素。空切片会选择对应轴上的所有元素。例如,如果
v
是一个向量,
v[::2]
会选择其中的每隔一个元素。
基于标量的索引
使用标量进行索引可以选择向量中给定位置的单个元素。例如,
v[3]
会选择向量中第四个位置的元素(索引从0开始)。
使用整数向量进行索引
想要通过整数索引选择向量中的部分元素时,可以传递一个整数列表。例如,如果
v
是一个向量,
v[[0, -1]]
会选择向量中的第一个和最后一个元素。
使用逻辑向量进行索引
使用逻辑向量进行索引可以根据条件选择元素。例如,如果
v
是一个向量,
v[v > 0]
会选择向量中所有大于0的元素。
13、切片返回现有数据的视图是什么意思?
切片返回现有数据的视图意味着它不需要对子集元素进行独立复制。也就是说,原始数据
x
和它的切片版本共享相同的内存。这在我们进行原地修改给定向量的操作时很重要,例如对切片后的向量进行修改会影响原始向量。
如:
y = np.array([6, 4, 8, 5, 1, 3, 2, 9, 7])
y[::2] *= 10
会修改
y
中的每隔一个元素,因为切片返回的是视图,和
y
共享内存;而用整数或逻辑向量索引时总是返回一个副本,如
y[ [1, 3, 5, 7] ] *= 10
不会修改原始的
y
,因为操作是在一个新的(临时)对象上进行的。
14、思考这句名言:并非所有能被计数的东西都有价值,也并非所有有价值的东西都能被计数。谈谈你对这句名言的理解。
这句名言深刻地揭示了数据计量与事物价值之间的复杂关系。
从数据科学的角度来看,在实际工作中存在大量可以被量化和计数的数据,但这些数据并不一定都对我们的分析和决策有实质性的帮助。例如,在一个电商网站中,可能会记录每一个用户的鼠标点击次数,虽然这个数据可以被精确地计数,但它对于了解用户的购买意愿和行为模式可能并没有太大的意义,即“
并非所有能被计数的东西都有价值
”。
而另一方面,有很多对于我们非常重要和有价值的事物,却难以用数字来进行准确的计量。比如一个公司员工的工作热情、创造力和团队合作精神等,这些因素对于公司的发展至关重要,但很难用具体的数字来衡量。在社会层面,人们的幸福感、文化的影响力等也都属于难以计数却非常有价值的范畴,也就是“
并非所有有价值的东西都能被计数
”。
对于数据科学家来说,理解这句名言意味着在工作中不能仅仅依赖于可量化的数据,还需要综合考虑那些难以计数但有重要价值的因素。在进行数据分析和决策时,要避免过度关注可计数的数据而忽略了其他重要的方面,同时也要尝试寻找合适的方法来衡量那些难以量化的因素,以更全面地了解和解决问题。
15、为什么说作为一名数据科学家可能是一份令人沮丧的工作?请结合‘有些重要的事情是可以被量化统计的,但我们不会去统计它们,因为我们超预算了,或者因为我们愚蠢的公司经理根本不在乎’进行分析。
数据科学家可能会遇到一些有价值的数据因预算限制或者管理层不重视而无法进行统计分析的情况。这反映出在实际工作中,数据科学不仅仅是技术层面的问题,还会受到经济和管理等多方面因素的制约。
对于数据科学家而言,一方面要具备专业的技能来处理数据,另一方面还需要应对工作环境中的各种非技术难题,比如争取资源、与管理层沟通等。
这种情况可能会让数据科学家感到自己的专业能力无法完全施展,从而产生沮丧情绪。同时也提醒我们,在推动数据科学项目时,需要综合考虑各种因素,不能仅仅关注技术和数据本身。
16、成为一名数据科学家可能是一份令人沮丧的工作,尤其是当你追求真相的时候。思考:有些重要的事情是可以被量化统计的,但我们不会去统计它们,因为可能会冒犯到一些人或让他们感到不快。请解释为什么这种情况会让数据科学家工作感到沮丧。
在数据科学领域,数据科学家追求真相,期望通过数据来准确反映现实和发现规律。然而,在实际操作中,存在一些重要的、可量化的数据却不能被统计。
这可能是因为这些数据涉及到敏感信息,例如:
个人隐私
种族
宗教
如果对这些数据进行统计和分析,可能会:
引发社会争议
冒犯到特定群体
或者让人们感到不舒服
从道德和伦理的角度来看,数据科学家有责任:
保护数据主体的权益和尊严
避免因数据的不当使用而造成伤害
这就要求数据科学家在进行数据收集和分析时,需要权衡:
数据的价值
可能带来的影响
有时候,为了避免潜在的负面影响,不得不放弃对某些数据的统计。但这种情况也给数据科学家带来了挑战:
因为这些被忽略的数据可能包含着重要的信息
对于全面理解问题和做出准确的决策是有帮助的
数据科学家需要在追求真相和遵循道德伦理之间找到平衡,这无疑增加了工作的复杂性和难度,也可能导致他们在工作中感到沮丧。
例如
:
在研究社会不平等问题时,某些关于收入差距、贫富分化的数据可能会揭示出社会的深层次矛盾,如果公布这些数据可能会引起社会动荡,数据科学家就需要谨慎处理。
17、为什么平均收入的概念会让公众感到困惑?
异常值对算术平均值的影响
算术平均值会受到非常大或非常小的观测值(即异常值)的强烈影响。例如,在收入数据中,如果加入一个亿万富翁,平均收入会大幅提高,这使得平均收入不能真实反映大多数人的实际收入情况。
此外,平均收入反映的是将所有财富集中起来再平均分配给每个人的情况,但在现实中,每个人对社会的贡献并不相同,因此平均收入的概念容易让公众感到困惑。
18、什么时候手动设置随机数生成器的种子是有意义的?
设置随机数生成器种子的意义
手动设置随机数生成器的种子是有意义的,原因如下:
1. 可重复性
设置种子能使我们进行完全可重复的数值实验,真正的科学研究倾向于在相同条件下得到相同的结果。例如,设置
np.random.seed(123)
后,每次运行
np.random.rand(5)
都会得到相同的数组:
array([0.69646919, 0.28613933, 0.22685145, 0.55131477, 0.71946897])
2. 多包依赖
许多Python包(如pandas和scikit-learn)依赖于numpy的随机数生成器,为了利用这些包,我们需要习惯调用
numpy.random.seed
。此外,一些函数(如
sklearn.model_selection.train_test_split
或
pandas.DataFrame.sample
)配备了
random_state
参数,其作用就像临时更改种子一样。
3. 避免数据操纵嫌疑
使用特定种子可能会让人怀疑有人为了证明某个观点而操纵数据,所以建议只坚持使用一个种子,如123,以保证基于模拟数据得出的结论更可信。
19、给定一个对数正态分布的样本x,我们如何将其转换为正态分布的样本,即y = f(x),其中f是什么?
由于对数正态分布的定义,如果随机变量 $ X $ 服从对数正态分布,那么 $ Y = ln(X) $ 服从正态分布。所以对于对数正态分布的样本 $ x $,函数 $ f(x) = ln(x) $ 可以将其转换为正态分布的样本 $ y $,即 $ y = ln(x) $。
20、如果A是一个有5行6列的矩阵,那么A.reshape(-1)、A.reshape(3, -1)、A.reshape(-1, 3)、A.reshape(-1, -1)、A.shape = (3, 10) 和 A.shape = (-1, 3) 分别是什么意思?
A.reshape(-1)
: 这里的“-1”是一个占位符,它表示让NumPy自动计算该维度的大小。由于矩阵A有5行6列,总共30个元素,所以
A.reshape(-1)
会将矩阵A转换为一个一维数组,该数组包含30个元素。
A.reshape(3, -1)
: 表示将矩阵A重塑为一个有3行的新矩阵,列数由NumPy根据元素总数自动计算。因为A总共有30个元素,所以新矩阵会有10列,即得到一个3行10列的矩阵。
A.reshape(-1, 3)
: 表示将矩阵A重塑为一个有3列的新矩阵,行数由NumPy根据元素总数自动计算。由于A有30个元素,所以新矩阵会有10行,即得到一个10行3列的矩阵。
A.reshape(-1, -1)
: 这种使用方式是错误的,在
reshape
方法中不能同时有两个“-1”占位符,因为NumPy无法同时推断两个维度的大小。
A.shape = (3, 10)
: 这是直接修改矩阵A的形状属性。将矩阵A的形状修改为3行10列,这意味着A会以一种新的视图来展示原来的数据,元素总数不变仍为30个。
A.shape = (-1, 3)
: 同样是修改矩阵A的形状属性,将矩阵A修改为有3列的矩阵,行数由NumPy根据元素总数自动计算。由于A有30个元素,所以新矩阵会有10行,即得到一个10行3列的矩阵。
21、列出一些向现有矩阵添加新行或列的方法。
向现有矩阵添加新行或列的方法有:
numpy.column_stack
和
numpy.row_stack
:
numpy.column_stack
和
numpy.row_stack
可以接受一个类数组对象的元组,并将它们按列或按行绑定以形成一个新矩阵。例如:
python
np.column_stack(([10, 20], [30, 40], [50, 60]))
和
python
np.row_stack(([10, 20], [30, 40], [50, 60]))
还可以使用
np.column_stack
结合
np.row_stack
进行更复杂的操作,如:
python
np.column_stack((np.row_stack(([10, 20], [30, 40], [50, 60])), [70, 80, 90]))
此外,还有一些可用于执行类似操作的方法,如
numpy.append
、
numpy.vstack
、
numpy.hstack
、
numpy.concatenate
和
numpy.c_
以及
numpy.insert
,但未详细展示其使用示例。
22、给出一些可视化三维数据的方法。
可视化三维数据的方法
使用三维散点图
这种方式效果不佳,因为是将三维现实投影到二维屏幕或平面页面上,会丢失一些信息。看到的内容与虚拟相机的位置有关,不同角度的意义可能不同。
– 可以通过调整
mpl_toolkits.mplot3d.axes3d.Axes3D.view_init
函数的参数来尝试找到有趣的仰角和方位角。
– 此外,还可以创建交互式散点图,在 Python 控制台运行相关代码后,能够用鼠标或触摸板自由重新定位虚拟相机,从而获得更多信息。
绘制散点图矩阵(pairs plot)
可以尝试将所选变量的所有成对组合以散点图矩阵的形式描绘出来,通过定义的
pairplot
函数实现。
23、Does numpy.mean(A, axis=0) compute the rowwise or columnwise means of A?
numpy.mean(A, axis=0)
computes the columnwise means of
A
. For example,
np.mean(A, axis=0)
gives an array of values which represent the means calculated along the columns of matrix
A
:
np.mean(A, axis=0) ## array([0.33333333, 0.53333333, 0.33333333, 0.4 ])
24、What are the possible ways to index a matrix?
There are several ways to index a matrix:
Slice-based indexing
: Indexing based on two slices selects a sub-matrix. For example,
A[::2, 3:]
selects every second row and skips the first three columns. An empty slice selects all elements on the corresponding axis, like
A[:, ::-1]
which selects all rows and reverses the columns.
Scalar-based indexing
: Indexing by a scalar selects a given row or column, reducing the dimensionality of the output object. For example,
A[:, 3]
selects the fourth column and gives a flat vector, and
A[0, -1]
yields the element in the first row and the last column.
Indexing with two integer vectors
: For example,
A[ [0, -1, 0, 2, 0], [1, 2, 0, 2, 1] ]
yields elements at specified positions. To select a sub-matrix using integer indexes, it is best to make sure that the first indexer is a column vector and the second one is a row vector, like
A[ [[0], [-1]], [[1, 3]] ]
.
Indexing with logical vectors
: It is best to convert logical vectors to integer ones first (e.g., by calling
numpy.flatnonzero
). We can also use the
numpy.ix_
function, like
A[ np.ix_( np.mean(A, axis = 1)>0.35, [0, 2, 3, 0] ) ]
, or apply indexing twice, such as
A[np.mean(A, axis = 1)>0.45, :][:, [0, 2, 3, 0]]
.
25、哪些类型的矩阵索引器会返回现有数组的视图?
Slice
– slice and slice – scalar indexing return a view of the existing array.
26、点积、欧几里得范数和欧几里得距离之间有什么关系?
欧几里得范数与欧几里得距离的关系
:给定两个点 $mathbf{u}=(u_1,cdots,u_m)$ 和 $mathbf{v}=(v_1,cdots,v_m)$ 在 $mathbb{R}^m$ 中,欧几里得距离定义为
|u−v|=(u1−v1)2+(u2−v2)2+⋯+(um−vm)2−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−√=∑i=1m(ui−vi)2−−−−−−−−−−√|u−v|=(u1−v1)2+(u2−v2)2+⋯+(um−vm)2=∑i=1m(ui−vi)2
这里 $|cdot|$ 表示欧几里得范数,即欧几里得距离是两点差向量的欧几里得范数。
对于一维数据($m = 1$),欧几里得距离
|u−v|=|u1−v1||u−v|=|u1−v1|
点积与欧几里得距离的关系
:给定两个等长向量 $mathbf{x},mathbf{y}inmathbb{R}^m$,它们差的点积
(x−y)⋅(x−y)=(x−y)(x−y)T=∑i=1m(xi−yi)2(x−y)⋅(x−y)=(x−y)(x−y)T=∑i=1m(xi−yi)2
而 $sum_{i = 1}^{m}(x_i – y_i)^2$ 是 $mathbf{x}$ 和 $mathbf{y}$ 之间欧几里得距离的平方。
所以,两个向量差的点积等于它们之间欧几里得距离的平方。
综上所述,欧几里得距离是两点差向量的欧几里得范数,而两个向量差的点积是它们欧几里得距离的平方,三者通过这些数学公式紧密相关。