新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
答案 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)