在for循环中避免R错误“replacement has length zero”

zzzyeukh  于 2023-07-31  发布在  其他
关注(0)|答案(2)|浏览(214)

我有一个数据框,如下所示,显示了某些公司的价值取决于一年:

#   company year value1 value2
# 1       1 2019      1     10
# 2       1 2020     11    110
# 3       1 2021    111   1110
# 4       2 2019      2     20
# 5       2 2021    222   2220
# 6       3 2019      3     30
# 7       3 2020     33    330
# 8       3 2021    333   3330

字符串
公司2在2020年的价值缺失。现在我想总结一下每个公司在某一年的价值,例如。2020年:

df_sum <- data.frame()

for (i in 1:3) {
  # number of the company
  df_sum[i, 1] <- i
  # sum of the company's values
  df_sum[i, 2] <- df[df$company == i & df$year == 2020, "value1"] + 
    df[df$company == i & df$year == 2020, "value2"]
}


R给出输出
xjj[iseq] <中出错- replacement的长度为零
因为公司2缺少2020的值,因此for循环终止。
我如何实现缺失值被视为“NA + NA = NA”(即:df_sum[2,2] is NA)”并且for循环不会终止?
数据框df_sum应该看起来像这样:

company | sum of values
-------------------------
1|      1 |           121
2|      2 |            NA
3|      3 |           363

数据

df <- structure(list(company = c(1, 1, 1, 2, 2, 3, 3, 3), year = c(2019, 
2020, 2021, 2019, 2021, 2019, 2020, 2021), value1 = c(1, 11, 
111, 2, 222, 3, 33, 333), value2 = c(10, 110, 1110, 20, 2220, 
30, 330, 3330)), class = "data.frame", row.names = c(NA, -8L))

5vf7fwbs

5vf7fwbs1#

首先,我认为jay.sf的答案更简洁,对我来说可能是一个更好(或更有效)的选择。然而,我已经写了下面的内容,所以我想我可能会与我的替代品。
选项1:要按原样使用for循环(几乎),您需要生成缺失的数据并使用NA填充它,例如使用嵌套循环。(我还将sum()改为+来对值求和)

df_full=data.frame(company=NULL, year=NULL, value1=NULL, value2=NULL)

#extract data
for(comp in 1:max(df$company)) { #per company
  for (yr in c(2019, 2020, 2021)){#per year
    
    #subset original dataframe by company and year
    dfsub=subset(df, company==comp & year==yr)
    
    if (sum(dfsub)==0) { #no data so output NA
        dfsub=data.frame(company=comp,
                         year=yr,
                         value1=NA,
                         value2=NA)
    } 
    
    #bind subset to output dataframe
    df_full=rbind(df_full, dfsub)
  }
}

#Now use your for loop on df_full
df_sum <- data.frame()

for (i in 1:3) {
  # number of the company
  df_sum[i, 1] <- i
  # sum of the company's values (notice change to sum() function)
  df_sum[i, 2] <- sum(df_full[df_full$company == i & df_full$year == 2020, "value1"], df_full[df_full$company == i & df_full$year == 2020, "value2"])
}

字符串
选项2:使用类似的嵌套循环一次对所有年份求和

df_sum <- data.frame(Company=NULL, value=NULL)

for(comp in 1:max(df$company)) { #per company
  for (yr in c(2019, 2020, 2021)){#per year
    
    #subset original dataframe by company and year
    dfsub=subset(df, company==comp & year==yr)
    
    if (sum(dfsub)==0) { #no data so output NA
      output=data.frame(company=comp, year=yr, value=NA)
    } else { #data exists so sum it
      output=data.frame(company=comp, year=yr, value=sum(dfsub$value1, dfsub$value2))
    }
    #bind output to df_sum
    df_sum=rbind(df_sum, output)
  }
}


希望有助于更明确地了解发生了什么,但有更有效的方法来完成这类事情

nfzehxib

nfzehxib2#

公司2在2020年没有观测值,所以你想分配给df_sum[i, 2] <-的长度为零,这就是错误所抱怨的。
你可以考虑处理一个if/else子句的情况,在这里我们分配NA_realif,没有any观察。

df_sum <- matrix(NA, nrow=length(unique(df$company)), ncol=2) |>
  as.data.frame() |>
  setNames(c('company', 'sum_of_values'))  ## *

for (i in 1:3) {
  # number of the company
  df_sum[i, 1] <- i
  # sum of the company's values
  v <- with(df, company == i & year == 2020)
  if (any(v)) {
    df_sum[i, 2] <- df[v, "value1"] + df[v, "value2"]
  } else {
    df_sum[i, 2] <- NA_real_
  }
}

df_sum
#   company sum_of_values
# 1       1           121
# 2       2            NA
# 3       3           363

字符串

  • 最好用它的大小初始化对象,当它在这种情况下已知时。其效果是,内存是预先分配的,因此速度要快得多。

如果没有for循环(在R中相当慢),你可以将cbind公司转换为rowSums两个值,到2020年将其子集化,并将merge公司转换为unique公司。

cbind(df['company'], 
      sum_of_values=rowSums(df[c('value1', 'value2')]))[df$year == 2020, ] |>
  merge(unique(df[c('company')]), all=TRUE)
#   company sum_of_values
# 1       1           121
# 2       2            NA
# 3       3           363

相关问题