使用 seq_along() 来处理空的情况
using seq_along() to handle the empty case
我读到使用 seq_along()
可以更好地处理空的情况,但这个概念在我的脑海中不是很清楚。
比如我有这个数据框:
df
a b c d
1 1.2767671 0.133558438 1.5582137 0.6049921
2 -1.2133819 -0.595845408 -0.9492494 -0.9633872
3 0.4512179 0.425949910 0.1529301 -0.3012190
4 1.4945791 0.211932487 -1.2051334 0.1218442
5 2.0102918 0.135363711 0.2808456 1.1293810
6 1.0827021 0.290615747 2.5339719 -0.3265962
7 -0.1107592 -2.762735937 -0.2428827 -0.3340126
8 0.3439831 0.323193841 0.9623515 -0.1099747
9 0.3794022 -1.306189542 0.6185657 0.5889456
10 1.2966537 -0.004927108 -1.3796625 -1.1577800
考虑这三个不同的代码片段:
# Case 1
for (i in 1:ncol(df)) {
print(median(df[[i]]))
}
# Case 2
for (i in seq_along(df)) {
print(median(df[[i]]))
}
# Case 3
for(i in df) print(median(i))
当存在完整的 data.frame
或存在空的 data.frame
时,这些不同的过程有什么区别?
在df <- data.frame()
的条件下,我们有:
案例 1 成为受害者...
Error in .subset2(x, i, exact = exact) : subscript out of bounds
而 情况 2 和 3 未 触发。
本质上,案例 1 中的错误是由于 ncol(df)
是 0
。这导致序列 1:ncol(df)
变为 1:0
,从而创建向量 c(1,0)
。在这种情况下,for
循环尝试访问向量 1
的第一个元素,它试图访问第 1 列 不 存在。因此,该子集被发现超出范围。
同时,在情况 2 和 3 中,for
循环永远不会执行,因为在它们各自的集合中没有要处理的元素,因为向量是 空。原则上,这意味着它们的长度为 0
.
由于这个问题具体涉及 seq_along()
到底发生了什么,让我们以传统的 seq_along
为例,构建一个完整的向量 a
并查看结果:
set.seed(111)
a <- runif(5)
seq_along(a)
#[1] 1 2 3 4 5
本质上,对于向量a
的每个元素,都有一个由seq_along
创建的相应索引可供访问。
如果我们现在将 seq_along
应用于上述情况中的空 df
,我们将得到:
seq_along(df)
# integer(0)
因此,创建的是一个零长度向量。沿着零长度向量移动非常困难。
因此,案例 1 保护不佳 空案例。
现在,根据传统假设,data.frame
中有一些数据,对于任何类型的开发人员来说,这是一个非常糟糕 的假设。 ..
set.seed(1234)
df <- data.frame(matrix(rnorm(40), 4))
所有 三个 案例将按预期运行。也就是说,您将收到 data.frame
.
每列的中位数
[1] -0.5555419
[1] -0.4941011
[1] -0.4656169
[1] -0.605349
我读到使用 seq_along()
可以更好地处理空的情况,但这个概念在我的脑海中不是很清楚。
比如我有这个数据框:
df
a b c d
1 1.2767671 0.133558438 1.5582137 0.6049921
2 -1.2133819 -0.595845408 -0.9492494 -0.9633872
3 0.4512179 0.425949910 0.1529301 -0.3012190
4 1.4945791 0.211932487 -1.2051334 0.1218442
5 2.0102918 0.135363711 0.2808456 1.1293810
6 1.0827021 0.290615747 2.5339719 -0.3265962
7 -0.1107592 -2.762735937 -0.2428827 -0.3340126
8 0.3439831 0.323193841 0.9623515 -0.1099747
9 0.3794022 -1.306189542 0.6185657 0.5889456
10 1.2966537 -0.004927108 -1.3796625 -1.1577800
考虑这三个不同的代码片段:
# Case 1
for (i in 1:ncol(df)) {
print(median(df[[i]]))
}
# Case 2
for (i in seq_along(df)) {
print(median(df[[i]]))
}
# Case 3
for(i in df) print(median(i))
当存在完整的 data.frame
或存在空的 data.frame
时,这些不同的过程有什么区别?
在df <- data.frame()
的条件下,我们有:
案例 1 成为受害者...
Error in .subset2(x, i, exact = exact) : subscript out of bounds
而 情况 2 和 3 未 触发。
本质上,案例 1 中的错误是由于 ncol(df)
是 0
。这导致序列 1:ncol(df)
变为 1:0
,从而创建向量 c(1,0)
。在这种情况下,for
循环尝试访问向量 1
的第一个元素,它试图访问第 1 列 不 存在。因此,该子集被发现超出范围。
同时,在情况 2 和 3 中,for
循环永远不会执行,因为在它们各自的集合中没有要处理的元素,因为向量是 空。原则上,这意味着它们的长度为 0
.
由于这个问题具体涉及 seq_along()
到底发生了什么,让我们以传统的 seq_along
为例,构建一个完整的向量 a
并查看结果:
set.seed(111)
a <- runif(5)
seq_along(a)
#[1] 1 2 3 4 5
本质上,对于向量a
的每个元素,都有一个由seq_along
创建的相应索引可供访问。
如果我们现在将 seq_along
应用于上述情况中的空 df
,我们将得到:
seq_along(df)
# integer(0)
因此,创建的是一个零长度向量。沿着零长度向量移动非常困难。
因此,案例 1 保护不佳 空案例。
现在,根据传统假设,data.frame
中有一些数据,对于任何类型的开发人员来说,这是一个非常糟糕 的假设。 ..
set.seed(1234)
df <- data.frame(matrix(rnorm(40), 4))
所有 三个 案例将按预期运行。也就是说,您将收到 data.frame
.
[1] -0.5555419
[1] -0.4941011
[1] -0.4656169
[1] -0.605349