在R中循环遍历数据框长度的正确方法

17

今天我进行了相当多的调试,令我沮丧的是,我发现:

for (i in 1:0) {
     print(i)
}

在 R 中,实际上会分别打印出 1 和 0。这个问题是在写代码时遇到的。

for (i in 1:nrow(myframe) {
     fn(i)
}
我原计划如果nrow(myframe)== 0就不执行,那么正确的更正方法是什么?

如果nrow(myframe)== 0,则我本意是不执行的。 正确的更正方法是什么?

if (nrow(myvect) != 0) {
    for (i in 1:nrow(myframe) {
        fn(i)
    }
}

还有没有更合适的方法在 R 中完成我想要做的事情呢?

5个回答

26
您可以使用seq_along代替:

vec <- numeric() 
length(vec)
#[1] 0

for(i in seq_along(vec)) print(i)   # doesn't print anything

vec <- 1:5

for(i in seq_along(vec)) print(i)
#[1] 1
#[1] 2
#[1] 3
#[1] 4
#[1] 5

更新后编辑

df <- data.frame(a = numeric(), b = numeric())
> df
#[1] a b
#<0 rows> (or row.names with length 0)

for(i in seq_len(nrow(df))) print(i)    # doesn't print anything

df <- data.frame(a = 1:3, b = 5:7)

for(i in seq_len(nrow(df))) print(i)
#[1] 1
#[1] 2
#[1] 3

4
对于向量,可以使用seq_along函数;对于数据框,可以使用seq_len函数。
for(i in seq_len(nrow(the.table)){
    do.stuff()
}

4
关于修改,请参考对应函数seq_len(NROW(myframe))。这就是为什么你不应该在for()循环中使用1:N,以防止替换N的任何值为0或负数。
另一种选择(只是隐藏了循环)是执行apply(myframe, 1, FUN = foo),其中foo是一个包含你想要对myframe的每一行执行的操作的函数,它可能只是从循环体中剪切和粘贴而来。

3

显然,之前的所有答案都可以完成这项工作。

我希望有一个类似于这样的东西:

rows_along <- function(df) seq(nrow(df))

然后

for(i in rows_along(df)) # do stuff

完全独特的回答,它只是一个包装器。但我认为它更易读/直观。

1
我认为在R中最恰当的方法是使用apply函数。很多时候,都有一个可以完成该任务的apply函数。而且很多时候,您不需要一个序列。
以下是一个将diff应用于每个列或每个行的示例。
> d <- data.frame(x = 1:5, y = 6:10)

在列之上,

> lapply(d, diff)
$x
[1] 1 1 1 1

$y
[1] 1 1 1 1

在编程中,跨行操作。
> apply(d, 1, diff)
[1] 5 5 5 5 5

再次遍历列,返回一个矩阵

> sapply(d, diff)
     x y
[1,] 1 1
[2,] 1 1
[3,] 1 1
[4,] 1 1

点击此链接了解关于apply的最佳解释。


“我认为在R中最合适的方法是使用apply函数”——恕我直言,我不认为这是好建议。有两种或更多的方法来做某件事情是可以的,但是“错误的方法”不能是最明显和通常可行的方法,“正确的方法”则落后于它;这只会让人们感到困惑。就此而言。 - Robert Dodier

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接