【问题标题】:R: Loop in a function to fill a data frameR:在函数中循环以填充数据框
【发布时间】:2020-05-19 17:43:32
【问题描述】:

我有三个气象站来为每个注册的变量创建一个气象数据寄存器和数据帧。例如:

HR 是包含三个站的注册相对湿度数据的数据帧,而 feed 是应保存每个变量的加权平均值的数据帧。在这种情况下,我只将该函数应用于相对湿度,以填充 Feed 数据框中的第二列。


HR<-data.frame(M5125=c(70,75,NA,NA),
               M5126=c(73,NA,NA,71.5),
               PRAA=c(NA,NA,NA,NA))

precip<-data.frame(M5125=c(16,NA,11,NA),
               M5126=c(7,NA,NA,13),
               PRAA=c(15,NA,NA,NA))

>HR
 .    M5125      M5126      PRAA
[1,]   70          73        NA
[2,]   75          NA        NA
[3,]   NA          NA        NA
[4,]   NA         71.5       NA


daily<-c('2015-10-11','2015-10-12','2015-10-13','2015-10-14')

feed<-data.frame(daily,HR_percent=NA,precip_mm=NA)

我想用加权平均值填充单个数据框,但每个站点的不同日期都有一些 NA。所以我创建了一个函数来根据情况填充它。

WAM<-data.frame(STATIONS=c('M5125','M5126','PRAA'),
                WEIGHT=c(5,2,1.6))

wamFunction<-function(MV,col){
  for (r in 1:nrow(feed)) {
    feed[r,col]<-weighted.mean(MV[r,],WAM[,2],na.rm = T)
  }
}

mapply(wamFunction,HR,2)
mapply(wamFunction,precip,3)

该函数应根据每个站点的可用性数据向单元格返回加权平均值

这是返回的错误:

[.default(MV, v, 2) 中的错误:尺寸编号错误

【问题讨论】:

  • 数据框 Feed 和 HR 的行数相同
  • 你能用文字描述一下你在做什么吗?我认为使用weighted.mean 函数(它有一个na.rm 参数)可能有一种更简单的方法。但是我很困惑,您的feed 样本数据似乎没有STATION 信息,而且我不知道您显示的HR 数据适合的位置。任何机会您都可以分享几行样本数据使其可重现?
  • dput() 是一种以复制/粘贴方式共享一些数据的简单方法,例如,dput(feed[1:10, ]) 用于feed 数据的前 10 行。
  • 当然,@GregorThomas。 HR 是包含三个站点的注册相对湿度数据的数据帧,而 feed 是应该为每个变量保存加权平均值的数据帧。在这种情况下,我只将该函数应用于相对湿度以填充馈送数据框中的第二列。
  • @GregorThomas,我尝试使用 weighted.mean 函数。它仅使用循环工作,但不能在函数内部使用。如果我有一个函数将其应用于每个变量的数据框会更好。 wamFunction

标签: r function loops dataframe


【解决方案1】:

这是一个函数,结构略有不同,但可以达到目的:

HR<-data.frame(M5125=c(70,75,NA,NA),
               M5126=c(73,NA,NA,71.5),
               PRAA=c(NA,NA,NA,NA))

precip<-data.frame(M5125=c(16,NA,11,NA),
               M5126=c(7,NA,NA,13),
               PRAA=c(15,NA,NA,NA))



# define the function
# df is the dataframe
# wgt is the weights to be used
# if append = TRUE, then a dataframe with the 
# weighted average column will be returned
# if append  = FALSE (default), then an array with 
# wighted avg will be returned

get_wgt_avg = function(df, wgt, append = FALSE){
  if(ncol(df) != length(wgt)){
    stop("number of columns in df and weights' length differ")
  }

  output <- rep(NA, nrow(df))
  for(i in 1:nrow(df)){
    output[i] <- weighted.mean(df[i,], w = wgt, na.rm = TRUE)
  }
  if(append){
    df$wgt_avg = output
    return(df)
  }else{
    return(output)
  }
}


# get weighted avg for the HR data
HR_Wgt_avg <- get_wgt_avg(HR, wgt = c(5, 2, 1.6))
print(HR_Wgt_avg)



# include column in the precip df
precip_2 <- get_wgt_avg(precip, wgt = c(5, 2, 1.6), append = TRUE)
print(precip)
print(precip_2)

【讨论】:

    【解决方案2】:

    我同意其他人的观点,即获取数据样本以进行检查会有所帮助。乍一看您的功能,我会假设您以无意的方式使用mapply。您的函数直接寻址数据框中的位置。但是,mapply 只会将列传递给 wamFunction

    您可以这样做检查:

    mapply(str, WAM)
    

    因此,像MV[v,2]这样的指令不能再工作了。

    【讨论】:

      【解决方案3】:

      我建议melt将您的数据集转换为长格式,然后您会发现无需使用循环即可更轻松地过滤掉 NA 等。这是一个使用data.table的示例:

      library(data.table)
      setDT(precip)
      precip[, day:=daily]  # Add in a "day" column to the data
      
      # Turn the data into long form, and filter out any NAs to leave only valid values
      precip.long <- melt(precip, id.vars='day', variable.name='STATIONS', value.name='precip')[!is.na(precip)]
      
      precip.long[WAM, WEIGHT:=i.WEIGHT, on='STATIONS']  # Join the weights in
      precip.long[, weighted.mean(precip, WEIGHT), by='day']  # Group by day and apply weighted mean
      

      【讨论】:

        猜你喜欢
        • 2012-11-06
        • 2018-09-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-01-11
        • 1970-01-01
        相关资源
        最近更新 更多