How to Put a Complicated Equation into a R Formula

How to put a complicated equation into a R formula?

Assuming you are using nls the R formula can use an ordinary R function, H(a, b, c, D), so the formula can be just h ~ H(a, b, c, dbh) and this works:

# use lm to get startingf values
lm1 <- lm(1/(h - 1.3) ~ I(1/dbh) + I(1/dbh^2), df)
start <- rev(setNames(coef(lm1), c("c", "b", "a")))

# run nls
H <- function(a, b, c, D) 1.3 + D^2 / (a + b * D + c * D^2)
nls1 <- nls(h ~ H(a, b, c, dbh), df, start = start)

nls1 # display result

Graphing the output:

plot(h ~ dbh, df)
lines(fitted(nls1) ~ dbh, df)

Sample Image

R Markdown Math Equation Alignment

I'm not quite sure what you're going for here, but line breaks, \\ go at the end of tthe line, not the beginning, and the aligmnent operator is &. So this:

$$
\begin{aligned}
AR(p): Y_i &= c + \epsilon_i + \phi_i Y_{i-1} \dots \\
Y_{i} &= c + \phi_i Y_{i-1} \dots
\end{aligned}
$$

produces this:

Sample Image

Creating a function to loop columns through an equation in R

As others have noted in the comments, there are quite a few syntax issues that prevent your code from running, as well as a few unstated requirements. That aside, I think there is enough to recommend a few improvements that you can hopefully build on. Here are the top line changes:

  • You likely don't need this to be a function, but rather a nested for loop (if you want to do this with base R). As written, the code isn't flexible enough to merit a function. If you intend to apply this many times across different datasets, a function might make sense. However, it will require a much larger rewrite.

  • Assuming you are fitting a simple regression via lm, then you can pull out the coefficient of interest via the $ operator and indexing (see below). Some thought will need to go into how to handle different models in the loop. Here, we assume you only need one coefficient from one model.

  • There are a few areas where the syntax is incorrect and a review of sub setting in base R would be helpful. Others have pointed out in the comments were some of these are.

Here is one approach were we loop through each subject (j) through each feature or subfield (i) and store them in a matrix (out). This is just an approach and will almost certainly need tweaking on your end!

#NOTE: the dataset your provided is saved as x in this example.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           

#fit a linear model - here we assume there is only one coef. of interest, but you may need to alter
# depending on how the slope changes in each calculation
reg <- lm(ICV ~ right_CA3, x)

# view the coeff.
reg$coefficients

# pull out the slope by getting the coeff. of interest (via index) from the reg object
slope <- reg$coefficients[[1]]

# list of features/subfeilds to loop through
sf <- c("left_presubiculum", "right_presubiculum",
"left_subiculum", "right_subiculum", "left_CA1", "right_CA1",
"left_CA3", "right_CA3", "left_CA4", "right_CA4", "left_GC-ML-DG",
"right_GC-ML-DG")

# matrix to store output
out <- matrix(ncol = length(sf), nrow = NROW(x))

#name the rows after each subject
row.names(out) <- x$Subject

#name the columns after each sub feild
colnames(out) <- sf

# nested for loop that goes by subject (j) and features/subfeilds (i)
for(j in x$Subject){

for (i in sf) {

out[j,i] <- as.numeric( x[x$Subject == j, i] - (slope * (x[x$Subject == j, "ICV"] - mean(x$ICV))) )

}

}

# check output
out

Extract numbers from chemical formula - including multiple elements within parentheses

Looks like you adapted your code to reuse the RegExp object as I suggested last time, and indeed I'd expect that to improve performance considerably. However I should have explained better how to implement but see the example below.

In the example I also took your second RegExp pattern but reworked the rest. This example seems to work for me with your sample data but that's all I've tested!

Option Explicit    
Private regEx As RegExp
Private regEx2 As RegExp

Sub Test()
' formulas in A2:A7 and elements in B1:H1 (see OP's screenshot), return results in B2:H7
Range("B2:H7").Value = CountElements(Range("A2:A7").Value, Range("B1:H1"))
End Sub

Function CountElements(ChemFormulaRange As Variant, ElementRange As Variant) As Variant
Dim RetValRange() As Long
Dim RetVal As Long
Dim ChemFormula As String
Dim i As Long, j As Long
Dim mpoints As Long, npoints As Long
Dim Element As String

If regEx Is Nothing Then
Set regEx = New RegExp
With regEx
.Global = True
'.MultiLine = True ' ? only if working with multilines
.IgnoreCase = False

'first pattern matches every element once
.Pattern = "([A][cglmrstu]|[B][aehikr]?|[C][adeflmnorsu]?|[D][bsy]|[E][rsu]|[F][elmr]?|[G][ade]|[H][efgos]?|[I][nr]?|[K][r]?|[L][airuv]|[M][cdgnot]|[N][abdehiop]?|[O][gs]?|[P][abdmortu]?|[R][abefghnu]|[S][bcegimnr]?|[T][abcehilms]|[U]|[V]|[W]|[X][e]|[Y][b]?|[Z][nr])([0-9]*)"
End With

Set regEx2 = New RegExp
With regEx2
.Global = True
'.MultiLine = True ?
.IgnoreCase = False

'second patternd finds parenthesis and multiplies elements within
.Pattern = "(\((.+?)\)([0-9])+)+?"
End With
End If

' Convert input ranges to variant arrays
If TypeName(ChemFormulaRange) = "Range" Then ChemFormulaRange = ChemFormulaRange.Value
If TypeName(ElementRange) = "Range" Then ElementRange = ElementRange.Value

'parameter
npoints = UBound(ChemFormulaRange, 1) - LBound(ChemFormulaRange, 1) + 1
mpoints = UBound(ElementRange, 2) - LBound(ElementRange, 2) + 1

'dimension arrays
ReDim RetValRange(1 To npoints, 1 To mpoints)

'calculate all values
For i = 1 To npoints
ChemFormula = ChemFormulaRange(i, 1)
For j = 1 To mpoints
RetVal = 0
Element = ElementRange(1, j)
Call ChemRegex(ChemFormula, Element, RetVal)
RetValRange(i, j) = RetVal
Next
Next

'output answer
CountElements = RetValRange

' Set regEx = Nothing: Set regEx2 = Nothing

End Function

Private Sub ChemRegex(ChemFormula, Element, RetVal)
Dim Matches As MatchCollection, Matches2 As MatchCollection
Dim m As Match, m2 As Match

Set Matches = regEx.Execute(ChemFormula)
For Each m In Matches
If m.SubMatches(0) = Element Then
RetVal = RetVal + IIf(Not m.SubMatches(1) = vbNullString, m.SubMatches(1), 1)
End If
Next m

If InStr(1, ChemFormula, "(") Then ' if the formula includes elements within parentheses
Set Matches2 = regEx2.Execute(ChemFormula)
For Each m2 In Matches2
Set Matches = regEx.Execute(m2.Value)
For Each m In Matches
If m.SubMatches(0) = Element Then
If m.SubMatches(1) = vbNullString Then
RetVal = RetVal + m2.SubMatches(2) - 1
Else
RetVal = RetVal + m.SubMatches(1) * (m2.SubMatches(2) - 1)
End If
End If
Next
Next m2
End If

End Sub

This could certainly be improved a little more by testing all the elements in one RegExp exectution as suggested by CDP1802, but I'll leave that to you!

Calculation formula of ARIMA model?

ARIMA(2,1,0) simply means that you

  1. differentiate the series, i.e. replace series by diff(series),
  2. then apply the formula for ARIMA(2,0,0), but to diff(series),
  3. finally "re-integrate" the result by cumsum.

The function fcst_ar2 contains the formula for ARIMA(2,0,0), fcst_diff_ar2 that for ARIMA(2,1,0):

library(forecast)

#--------------------------------------------------------

fcst_ar2 <- function( coef, series, horizon )
{
y <- as.vector(series) - coef[3]

for ( i in 1:horizon ) {
y <- c( y, coef[2:1] %*% tail(y,2) )
}

return( y + coef[3] )
}

#--------------------------------------------------------

fcst_diff_ar2 <- function( coef, series, horizon )
{
y <- as.vector(series)

return( cumsum( c(y[1], fcst_ar2( c(coef,0), diff(y), horizon ) ) ) )
}

#========================================================
# Example:

a<-c(198,150,120,84,150,136,80,128,160,132,144,234,300,312,400,468,420,500,650,612,516)
series<-ts(a,frequency=1,start=c(1990))
fit<-Arima(series,c(2,0,0),method="ML")
fit2<-Arima(series,c(2,1,0),method="ML")

#--------------------------------------------------------
fcst_ar2( coef(fit), series, 3 )
# [1] 198.0000 150.0000 120.0000 84.0000 150.0000 136.0000 80.0000 128.0000
# [9] 160.0000 132.0000 144.0000 234.0000 300.0000 312.0000 400.0000 468.0000
# [17] 420.0000 500.0000 650.0000 612.0000 516.0000 468.1754 438.8091 417.5725

forecast( fit, 3 )
# Point Forecast Lo 80 Hi 80 Lo 95 Hi 95
# 2011 468.1754 389.9369 546.4138 348.5200 587.8308
# 2012 438.8091 317.0562 560.5621 252.6041 625.0142
# 2013 417.5725 266.9412 568.2038 187.2018 647.9432

#--------------------------------------------------------
fcst_diff_ar2( coef(fit2), series, 3 )
# [1] 198.0000 150.0000 120.0000 84.0000 150.0000 136.0000 80.0000 128.0000
# [9] 160.0000 132.0000 144.0000 234.0000 300.0000 312.0000 400.0000 468.0000
# [17] 420.0000 500.0000 650.0000 612.0000 516.0000 504.6897 535.3388 547.1413

forecast( fit2, 3 )
# Point Forecast Lo 80 Hi 80 Lo 95 Hi 95
# 2011 504.6897 428.9867 580.3927 388.9119 620.4675
# 2012 535.3388 413.7918 656.8858 349.4487 721.2289
# 2013 547.1413 405.0444 689.2383 329.8228 764.4599


Related Topics



Leave a reply



Submit