我提前道歉,我觉得以书面形式准确的问题表达非常困难,并认为这是通过查看代码最清晰。另外,我是比较新的R和必须使用合适的语言来准确地描述这种情况的麻烦。我认为解决的办法应该是很容易被人带着几分更多的经验指出,任何建议将不胜感激!
我有我努力让自己在一组,由组的基础为此我写了一个功能的专门计算。功能是用户定义执行该专门的计算,需要4个参数(其中2个具有长度> 1),并输出一个值(因此输出不等于输入的长度)。虽然这种功能不工作,我需要能够高效率地将其应用到每个组中的数据帧(对于下面的重复的例子,有4个组,但是,在现实中,将有数百或基团的1000)。
我试图用应用功能,通常建议对于那些听起来类似这样的情况,但我至今没有成功使用非for循环的方法。我认为这是因为在数据帧中的每一行不与不同组相关联,而有与单个基团(下面再现的示例相关联的多个行有与每个基团,其是相同的相关联的21行实际数据)。
无论如何,这似乎是一个for循环将是我的功能应用到每个组相关联的行的简单方法。然而,我无法生成所需的输出。正如我在序言中提到,我觉得这只是因为我眺望/不知道的东西很基本的,如需要做一个循环或索引我的for循环里面不同的循环。
interval=0.05 #used here to generate v1 and again in the function
v1 = seq(0.00000000001,1.00000000001, by=interval)
nrows = length(v1) #determines length of other variables
g1 = c(rep(23.4, nrows), rep(19.7, nrows),rep(25.2, nrows),rep(16.4,
nrows))
v2 = runif(length(g1), 0,1)
dat = as.data.frame(cbind(g1,v1,v2))
哪里:
(这是我的第一个功能,我想有一个更好的方式来写,但它的工作)
MyFunction = function(v1, v2, interval, nrows) {
sum.prod = sum(v1[2:nrows-1] * v2[2:nrows-1])
last.val = v2[nrows]/2
out = 2 * (sum.prod+last.val) * interval
out
}
我提供了第一组变量计算(G1 = 23.4),以防万一它是有帮助的,以确认该功能的工作原理以及它是如何工作的,因为有这个功能没有文档
range1 = 1:nrows
g1.sub1 = dat$g1[range1]
v1.sub1 = dat$v1[range1]
v2.sub1 = dat$v2[range1]
g.first = 2 * ((v1.sub1[2] * v2.sub1[2])+
(v1.sub1[3] * v2.sub1[3]) + (v1.sub1[4] * v2.sub1[4]) +
(v1.sub1[5] * v2.sub1[5]) + (v1.sub1[6] * v2.sub1[6]) +
(v1.sub1[7] * v2.sub1[7]) + (v1.sub1[8] * v2.sub1[8]) +
(v1.sub1[9] * v2.sub1[9]) + (v1.sub1[10] * v2.sub1[10]) +
(v1.sub1[11] * v2.sub1[11]) + (v1.sub1[12] * v2.sub1[12]) +
(v1.sub1[13] * v2.sub1[13]) + (v1.sub1[14] * v2.sub1[14]) +
(v1.sub1[15] * v2.sub1[15]) + (v1.sub1[16] * v2.sub1[16]) +
(v1.sub1[17] * v2.sub1[17]) + (v1.sub1[18] * v2.sub1[18]) +
(v1.sub1[19] * v2.sub1[19]) + (v1.sub1[20] * v2.sub1[20]) +
v2.sub1[21] / 2) * interval
g.first
其中由给定的值相匹配:
MyFunction(v1 = v1.sub1, v2 = v2.sub1, interval = interval, nrows=nrows)
正如我在说明中提到,我已经试过各种方法来解决这个问题,包括申请家庭的功能没有运气。下面的代码表示我来最接近的一次。然而,这只是给我的第一个元素在G1(23.4)的正确值,而不是四次,每次的四大要素在G1(23.4,19.9.25.2,16.4)正确的值一次。
g=c(unique((g1)))
out=NULL
for(i in seq_along(g)){
out[i]=MyFunction( v1 = v1, v2 = v2, interval = interval, nrows =
nrows)
}
out
我可以强制上述用于循环以产生类似于所期望的结果的东西,但该范围必须为每个组指定,并且由于实际数据具有基团,而不是仅仅4基团和基团的总数的100秒是事先不知道这不是一个可行的解决方案。
g=c(unique((g1)))
range1 = 1:nrows
range2 = (nrows+1):(nrows*2)
range3 = (nrows*2+1):(nrows*3)
range4 = (nrows*3+1):(nrows*4)
out1=NULL
out2=NULL
out3=NULL
out4=NULL
for(i in seq_along(g)){
out1[i]=MyFunction( v1 = dat$v1[range1], v2 = dat$v2[range1],
interval = interval, nrows = nrows)
out2[i]=MyFunction( v1 = dat$v1[range2], v2 = dat$v2[range2],
interval = interval, nrows = nrows)
out3[i]=MyFunction( v1 = dat$v1[range3], v2 = dat$v2[range3],
interval = interval, nrows = nrows)
out4[i]=MyFunction( v1 = dat$v1[range4], v2 = dat$v2[range4],
interval = interval, nrows = nrows)
}
out1
out2
out3
out4
理想情况下,最终输出将是一个表/矩阵/列表/数据包含g1的每个值,并通过函数“去”相应的输出值的帧
就像是:
g1 out
23.4 some value between 0 and 1
19.9 some value between 0 and 1
25.2 some value between 0 and 1
16.4 some value between 0 and 1
由于我的“尝试排除For循环”最终能够以不希望的方式提供正确的输出,尽管(劳动强度大,不可扩展,并输出4个相同值的每个组的每个组,而不是1倍的值),我认为这表明我的代码是缺乏一些基本的东西(例如,另一个循环,不同的变量seq_along,索引不当等)。我希望这是容易让有经验的用户识别和解释,因为我难住了。
提前致谢!
我知道你问一个for循环,但是因为你可能已经见过的,通常有一种更好的方式来做到这一点。我猜你不熟悉data.table
包呢,把它当做一个增压data.frame
。
所以,你想要做的是应用MyFunction
您的数据,由列g1
分组。这可以在data.table
通过以下方式轻松实现。
library(data.table)
DT <- as.data.table(dat)
DT[, .(out = MyFunction(v1, v2, interval, .N)), by = g1]
那么这些行做的是库(您可能必须与install.packages('data.table')
先安装它,然后你data.frame
转换为data.table
。最后,计算列out
为MyFunction
应用于v1, v2, interval and .N
由.N
分组(认为g1
为NROWS的)第一负荷。
我认为,这达到自己的目标,如果你有任何问题随时问。希望这可以帮助。
下面是一个使用tidyverse的方法。
首先,让我们看一下例子,有几行,捕捉你所描述的精简处理中更换的MyFunction:
library(tidyverse)
dat %>%
slice(1:21) %>% # Just the first grouping variable
slice(2:n()) %>% # Exclude first row; has small impact since v1[1] is nearly zero already...
mutate(prod = if_else(row_number() < n(), # For all rows but the last one in the group,
v1 * v2, # ... get the product of v1 and v2
v2/2)) %>% # ... or have of v2, for the last row
summarize(out = 2 * sum(prod) * interval) # Sum the "prod" row, * 2 * interval
# out
#1 0.5980449
要为G1的所有组做到这一点,我们要补充group_by
第一,然后做同样的总结步骤分别对每个组:
dat %>%
group_by(g1) %>%
slice(1:21) %>% # Just the first grouping variable
slice(2:n()) %>% # Exclude first row; has small impact since v1[1] is nearly zero already...
mutate(prod = if_else(row_number() < n(), # For all rows but the last one in the group,
v1 * v2, # ... get the product of v1 and v2
v2/2)) %>% # ... or have of v2, for the last row
summarize(out = 2 * sum(prod) * interval) # Sum the "prod" row, * 2 * interval
## A tibble: 4 x 2
# g1 out
# <dbl> <dbl>
#1 16.4 0.342
#2 19.7 0.514
#3 23.4 0.598
#4 25.2 0.568