R在单个观察中插入数据

时间:2014-07-15 01:44:17

标签: r

新R用户在使用SAS 20年后转换,并且在我独立时奋斗了10年。需要一种更有效的方法来插入大型数据库中的单个记录(五个260,000个观察数据集)。我将每小时电流曲线减少到4个参数,VS(表面电流)DZ(零速度深度),DH(中深度点),Vh(中深度速度)。下面给出了如何使用参数的示例和关键。对于单个观察,我可以在记录中插入如下

    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。不幸的是,当输入数据帧的列时,这会失败。我能解决这个问题的唯一方法是逐行处理文件,如下所示。我现在正处于处理的第二个小时。

   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          

3 个答案:

答案 0 :(得分:0)

如果要将相同的函数应用于数据框的多行,则需要使用plyr包。您还没有指定输出的外观,所以我会猜测。 daply会将您为一行创建的函数应用于每一行。

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包。

答案 1 :(得分:0)

我从未使用approx因此我不熟悉语法,但您可以使用apply(基础R)或daply(包plyr)。

基础R解决方案:

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含义&#34;维度1&#34;或&#34;保证金1,&#34;即行。第三个参数是一个应用于每一行的函数。

可能的plyr解决方案:

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
    })

在这种情况下唯一的区别是,而不是指定&#34;边距,&#34;使用.的{​​{1}}函数plyr指定一个向量,指示行属于哪个组。由于在这种情况下每行都是自己的组,因此分组向量就是行索引。

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

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

答案 2 :(得分:-1)

没有什么比发布一个问题来组织你的想法。简单的解决方案是不要将圆形栓钉强制成方形,而是简单地插入。简单的例子如下。工作在几秒钟内完成。我在3小时后仍然运行约函数。

写得不好,解决方案如下。

#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)

如果我将其简化为函数调用(例如下面的函数调用,我现在用它来平均来自平均曲线的给定深度的电流),这可以简化。

#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)