【问题标题】:How to run for-loops for parts of data frame at the time?当时如何为部分数据帧运行for循环?
【发布时间】:2020-05-13 22:36:07
【问题描述】:

这里有一个 R 新手!我有一个数据框,其中有相同 ID 的多个测量值。这是一个简化的例子。

id<-c(1,1,1,2,2,2,3,3,3)
x<-as.numeric(c(1:9))
y<-c(2,4,1,5,7,3,9,6,8)
z<-rep("text",9)
cal<-0
df<- data.frame(id, x, y,z,cal)

我想分别对每个 ID 的测量值运行以下循环,因为我想分别为不同的 ID 绘制校准值。

for (j in 2:length(df$x))
  {if (df$x[j]>=df$y[j]) {df$cal[j]<-df$x[j]+df$y[j-1]
  }else{
     df$cal[j]<- df$x[j]-df$y[j-1]
    }
  }

所以基本上我希望循环通过第一个 ID 运行,然后跳到第二个,然后是第三个,依此类推。预期结果将是以下数据框(0 是巧合):

> df
  id x y    z cal
1  1 1 2 text   0
2  1 2 4 text   0
3  1 3 1 text   7
-----------------
4  2 4 5 text   0
5  2 5 7 text   0
6  2 6 3 text   13
-----------------
7  3 7 9 text   0
8  3 8 6 text   17
9  3 9 8 text   15

由于我不想为每个 ID 创建数据帧的子集,因此我也尝试对 ID 使用 for 循环。

for (i in 1:3)
{if (df$id==i) {
  for (j in 2:length(df$x))
  {if (df$x[j]>=df$y[j]) {df$cal[j]<-df$x[j]+df$y[j-1]
  }else{
     df$cal[j]<- df$x[j]-df$y[j-1]
    }
  }
}
} 

但是,这给出了以下警告:1: In if (df$id == i) { : the condition has length > 1 and only the first element will be used

所以,我现在知道这是因为我试图将一个向量与另一个应该给出“TRUE”或“FALSE”的向量进行比较。但是,比较不同行的 ID 也无济于事,因为我需要手动更改 ID 值,例如for (i in 1:length(which(df$id==1)))

我一直在尝试找出其他方法来做到这一点,但还没有找到答案。任何帮助将不胜感激!

【问题讨论】:

  • 您能添加一个您预期输出的样本吗?
  • @NelsonGon 我添加了我希望拥有的数据框类型。

标签: r dataframe for-loop subset


【解决方案1】:
library(tidyverse) # this loads several packages that will help you.

df %>% # now you take your df
    mutate(cal = if_else(x >= y # and calculate the column cal
                         , x + lag(y) # if x >= y then calculate this
                         , x - lag(y))) # else calculate this

  id x y    z cal
1  1 1 2 text  NA
2  1 2 4 text   0
3  1 3 1 text   7
4  2 4 5 text   3
5  2 5 7 text   0
6  2 6 3 text  13
7  3 7 9 text   4
8  3 8 6 text  17
9  3 9 8 text  15

你不需要循环。 R是矢量化的。 lag() 创建一个被“移动”一个元素的向量。

不清楚问题的第二部分是关于什么的,但您是否正在寻找这个?

df %>%
    group_by(id) %>%
    mutate(cal = if_else(x >= y
                         , x + lag(y)
                         , x - lag(y)))

    id     x     y z       cal
<dbl> <dbl> <dbl> <fct> <dbl>
    1     1     1     2 text     NA
    2     1     2     4 text      0
    3     1     3     1 text      7
    4     2     4     5 text     NA
    5     2     5     7 text      0
    6     2     6     3 text     13
    7     3     7     9 text     NA
    8     3     8     6 text     17
    9     3     9     8 text     15

【讨论】:

  • 谢谢@Georgery!这看起来更直接的方式来做到这一点。如果我想在 x > y 的情况下将 x 作为新的 cal 并在 x cal= if_else(x >= y, x, lag(cal))?
  • 我不完全确定你的意思,但在mutate() 你也可以计算这个新版本。您也可以将其分配给另一个变量:mutate(cal2 = if_else(x &gt;= y, x, lag(cal))
  • 太好了,我就是这个意思。谢谢!
猜你喜欢
  • 1970-01-01
  • 2020-09-26
  • 2019-10-26
  • 1970-01-01
  • 2019-10-09
  • 1970-01-01
  • 2019-08-24
  • 1970-01-01
  • 2021-09-26
相关资源
最近更新 更多