0

我有一个像这样的数据框:

rel      <- c(2, 5, NA, 3, 6)
year.in  <- c(4, NA, 2, 3, 2)
year.out <- c(6, 7, NA, 5, 4)
year.1   <- c(NA, NA, NA, NA, NA)
year.2   <- c(NA, NA, NA, NA, NA)
year.3   <- c(NA, NA, NA, NA, NA)
year.4   <- c(NA, NA, NA, NA, NA)
year.5   <- c(NA, NA, NA, NA, NA) 

df <- as.data.frame(cbind(rel, year.in, year.out, year.1, year.2, year.3, 
                      year.4, year.5))

我想做的是用'rel'的值更新year.1 - year.5中的缺失值,但前提是:(year.in >= year.i AND year.out <= year.i) (我是 1:5)

专注于刚刚入学的那一年,我想出了这个:

for (i in 1:5) ifelse(df$year.in < i,
    df[paste("year", i, sep= ".")]<- NA,
    df[paste("year", i, sep= ".")]<- df["rel"])

但这只是将所有 year.i 变量替换为 rel 的值。

我有两个问题:

  • 如何在提到的条件下使用“rel”值更新 year.i 变量?

  • 在这里使用 if else 语句不好吗?

最好的,并提前感谢,

理查德

4

2 回答 2

4
library(data.table)
dt = data.table(df)

for(i in 1:5) dt[year.in <= i & i <= year.out, paste0('year.', i) := rel]

dt
#   rel year.in year.out year.1 year.2 year.3 year.4 year.5
#1:   2       4        6     NA     NA     NA      2      2
#2:   5      NA        7     NA     NA     NA     NA     NA
#3:  NA       2       NA     NA     NA     NA     NA     NA
#4:   3       3        5     NA     NA      3      3      3
#5:   6       2        4     NA      6      6      6     NA
于 2013-07-15T21:00:38.133 回答
1

melt使用包获取您的数据reshape2

library(reshape2)    
df.melt <- melt(df, id.vars=c('rel', 'year.in', 'year.out'))

挖出数字年份:

df.melt$year <- as.integer(gsub('year\\.', '', df.melt$variable))

然后使用向量化操作:

subsetter <- with(df.melt, year.in >= year & year.out <= year.out)
subsetter[is.na(subsetter)] <- FALSE
df.melt$value[subsetter] <- df.melt$rel[subsetter]

但是,在您的示例中,一切都不符合您的条件。

使用ifelse是完全可以接受的,但是,不要在里面做赋值。而是将其结果分配给某些东西,如下所示。问题是您在其中执行的两个任务ifelse不是在每个子集上,而是就像它们只是独立运行一样。

for (i in 1:5) {
  year_col <- paste('year', i, sep='.')
  df[[year_col]] <- ifelse(df$year.in >= i & df$year.out <= i,
                         df$rel,
                         df[[year_col]])
}

要回答你的子弹:

  • 往上看。

  • 使用没有什么特别的错误,ifelse有时为了可读性这样做很方便。然而,它是一个“循环”结构,因此通常可以被更有效的矢量化解决方案所取代。

于 2013-07-15T20:50:48.540 回答