首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >R跨单个观测值插入数据

问R跨单个观测值插入数据
EN

Stack Overflow用户
提问于 2014-07-15 09:44:17
回答 3查看 94关注 0票数 0

新的R用户在使用SAS 20年后发生了变化,当我独立后,我与excel斗争了10年。需要一种更有效的方法来跨大型数据库(五个260,000个观测数据集)上的单个记录进行插值。我将每小时的电流分布减少到4个参数,VS (表面电流) DZ (零速深度),DH (中深点),Vh (中深速)。下面给出了如何使用这些参数的示例和关键字。对于单个观测值,我可以对记录进行插值,如下所示

代码语言:javascript
复制
    DH = 60; Vh=100;VS=200;DZ=100        
    x = (c(0,DH, DZ))
    y = (c(VS,VH,0))
    Vh50 = approx(x=x,y=y,xout=50,method="linear",rule=1:1,ties="max")$y

近似很好地将范围值设置为NA。不幸的是,当输入一列数据帧时,这会失败。我可以解决这个问题的唯一方法是逐行处理文件,如下所示。我现在正在处理我的第二个小时。

代码语言:javascript
复制
   Input$DHtemp = ifelse(Input$DH>Input$DZ,Input$DZ,Input$DH)   
   n=max(Input$rank);n
   Input$x=cbind(Input$D0,Input$DHtemp,Input$DZ)
   Input$y=cbind(Input$VS,Input$VH,Input$VZ)
   head(Input)
   for (i in seq(from=1, to=n, by=1)) { 
      Input[i,"V50"] = approx(x=c(Input[i,"D0"],Input[i,"DHtemp"],Input[i,"DZ"]),
           y=c(Input[i,"VS"],Input[i,"VH"],Input[i,"VZ"]),
           xout=Input[i,"V_1"],method="linear",rule=1:1,ties="max")$y
          }

    DATA AND KEY TO DATA 

    HRS VS  DZ  DH  VH      KEY to data
    1   209 109 106 11      Depth   Speed
    2   211 111 109 8       0        VS
    3   213 112 110 9       DH       VH
    4   213 113 109 16      DZ       0
    5   215 115 111 16          
    6   216 118 114 13          
EN

回答 3

Stack Overflow用户

发布于 2014-07-15 12:26:29

如果要将同一函数应用于数据框的许多行,则需要使用plyr包。您还没有指定输出应该是什么样子,所以我来猜一猜。daply会将您为一行创建的函数应用到每一行。

代码语言:javascript
复制
library(plyr)

Input <- data.frame(HRS = c(1, 2, 3, 4), 
                    VS = c(209, 211, 213, 213),  
                    DZ = c(109, 111, 112, 113),  
                    DH = c(106, 109, 110,109),  
                    VH = c(11, 8, 9, 16))

approx_frame <- function(df) {
  x <- c(0, df$DH, df$DZ)
  y <- c(df$VS, df$VH, 0)
  result <- approx(x=x, y=y, xout=50, method="linear", rule=1:1, ties="max")
  return(result$y)
}

daply(Input, "HRS", approx_frame)

如果这对您来说仍然太慢,您将需要查看data.table包。

票数 0
EN

Stack Overflow用户

发布于 2014-07-15 12:37:06

我从未使用过approx,所以我只是不熟悉它的语法,但是您可以并且应该使用apply (基数R)或daply (包plyr)来代替循环遍历行。

基础R解决方案:

代码语言:javascript
复制
Input[,"V50"] <- apply(Input,1,function(row){
    approx(x=row["D0"],row["DHtemp"],row["DZ"]),
       y=c(row["VS"],row["VH"],row["VZ"]),
       xout=row["V_1"],method="linear",rule=1:1,ties="max")$y
    })

第一个参数是数据帧或矩阵。第二个参数是1,意思是“维度1”或“边距1”,即行。第三个参数是应用于每一行的函数。

一种可能的plyr解决方案:

代码语言:javascript
复制
Input[,"V50"] <- daply(Input,.(1:n),function(row){
    approx(x=row["D0"],row["DHtemp"],row["DZ"]),
       y=c(row["VS"],row["VH"],row["VZ"]),
       xout=row["V_1"],method="linear",rule=1:1,ties="max")$y
    })

在这种情况下,惟一的区别是不是指定“边距”,而是使用plyr中的函数.指定一个向量,该向量指示一行所属的组。因为在这种情况下,每一行都是它自己的组,所以分组向量就是行索引。

还有一个函数aaply,它的语法与apply相同,但通过类比,它不会返回您认为的结果。要使用页边距语法而不是组语法,您需要使用laply,然后对输出调用as.vector。我想听听其他用户关于aaply在这里做些什么。

请注意,plyr往往比基数R更快,但有时使用起来会更复杂。正如另一个答案所提到的,还有相关的data.table包和dplyr包,它(我认为)是plyr的一个版本,在某种程度上进行了优化。

票数 0
EN

Stack Overflow用户

发布于 2016-09-11 07:10:00

没有什么比发一个问题来组织你的想法更好的了。简单的解决方案是不强制将圆形钉成正方形,而是简单地插值。下面是一个简单的例子。作业在几秒钟内运行。我对近似函数的强制拟合在3小时后仍在运行。

这个解决方案写得并不优雅,如下所示。

代码语言:javascript
复制
#Interpolate velocity profile to standard depths
#  x is depth
#  y is velocity
#  xi = desired depths
# DH = thickness of upper layer
# DH = thickness of lower layer
# VS = surface speed
# VH = speed at depth H
InputOWIhr$D0 = 0
InputOWIhr$VZ =0
InputOWIhr$V_1=25
InputOWIhr$V_2=50
InputOWIhr$V_3=200
InputOWIhr$V_4=400

attach(InputOWIhr)
### reset this so that V = 0 if target is deeper than DZ
InputOWIhr$V25 =    ifelse(InputOWIhr$V_1<=InputOWIhr$DH,VS+(V_1)*(VS-
  VH)/(0-DH),ifelse(V_1>DZ,0,VH-(DH-V_1)*(VH-0)/(DH-DZ)))
InputOWIhr$V50 =    ifelse(InputOWIhr$V_2<=InputOWIhr$DH,VS+(V_2)*(VS-
    VH)/(0-DH),ifelse(V_2>DZ,0,VH-(DH-V_2)*(VH-0)/(DH-DZ)))
InputOWIhr$V200 =   ifelse(InputOWIhr$V_3<=InputOWIhr$DH,VS+(V_3)*(VS-
    VH)/(0-DH),ifelse(V_3>DZ,0,VH-(DH-V_3)*(VH-0)/(DH-DZ)))
InputOWIhr$V400 =   ifelse(InputOWIhr$V_4<=InputOWIhr$DH,VS+(V_4)*(VS-
    VH)/(0-DH),ifelse(V_4>DZ,0,VH-(DH-V_4)*(VH-0)/(DH-DZ)))
detach(InputOWIhr)

如果我将它简化为一个函数调用,就可以简化这一过程,就像下面这样,我现在使用它来从平均剖面插值给定深度的电流。

代码语言:javascript
复制
#Interpolate velocity profile from mean at standard depths
#  x is depth
#  y is velocity
#  xi = desired depths

VbarGOM <- function(Zi) { 
    Z=c(0,50,100,200,400,800,1200,1325)
    Vbar=c(35.26640258,28.74863283,22.23086307,19.22705602,13.20431536,6.676782584,4.677900862,5.6489939)
    result = approx(x=Z,y=Vbar,xout=Zi,method="linear",rule=1:1,ties="max")$y
    return(result)
    }

VbarGOM(10)    
票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/24748685

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档