问题
I am trying to create is a system of equations for a specific variable using dplyr
and prod
from a dataframe of strings to be used in an ordinary differential solver in R (deSolve
). The location of the variable dictates the form of the equation and therefore I am using grep
, filter_at
, mutate_at
, and apply
.
Constructing the equation depends on the column of the string/variable of interest based off the following i.
If a variable is ever found as a product
(P1,P2,P3)
then multiply:+1 * Rate * R1c * R1 * R2c * R2 * R3c * R3 * (P1c or P2c or P3c)
What I am trying to convey with that last term
(P1c or P2c or P3c)
is that depending on where the variable is(P1,P2 or P3)
then you need to multiply by the corresponding(P1c, P2c, or P3c)
, but not all of them- If a variable is found as a reactant
(R1,R2,R3)
then multiply-1 * Rate * R1c * R1 * R2c * R2 * R3c * R3
- I then want to add everything together and set it equal to “dVariable”
dVariable = Sum(all product expressions) + Sum(all Reactant expressions)
An example data frame that I have trimmed down is below.
structure(list(
Reaction = c("k3", "k4", "k40", "k38", "k39", "k44"),
Rate = c("kHV_H2O2", "kHV_HO2-", "3", "27000000", "5500000000", "6600000000"),
R1c = c(1, 1, 1, 1, 2, 1),
R1 = c("H2O2", "HO2-", "HO2$", "$OH", "$OH", "$OH"),
R2c = c(NA, NA, 1, 1, NA, 1),
R2 = c(NA, NA, "H2O2", "H2O2", NA, "HO2$"),
R3c = c(NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_),
R3 = c(NA_character_, NA_character_, NA_character_, NA_character_, NA_character_, NA_character_),
P1c = c(2, 1, 1, 1, 1, 1),
P1 = c("$OH", "$OH", "O2", "HO2$", "H2O2", "O2"),
P2c = c(NA, 1, 1, 1, NA, 1),
P2 = c(NA, "O$-", "$OH", "H2O", NA, "H2O"),
P3c = c(NA, NA, 1, NA, NA, NA),
P3 = c(NA, NA, "H2O", NA, NA, NA)),
row.names = c(NA, -6L), class = c("tbl_df", "tbl", "data.frame"))
If we consider $OH as the species of interest, then:
- in Row 1
$OH
is first found as a product inP1
with aP1c
of 2,
therefore:+1 * (kHV_H2O2) * (1) * (H2O2) * (2)
- In row 4
$OH
is first found as a reactant inR1
, therefore-1 * (27000000) * ($OH) * (1) * (H2O2) *(1)
Lastly, combining the two as a new variable gives
d$OH = +1 * (kHV_H2O2)*(1)*(H2O2)*(2) - 1 * (27000000)*($OH)*(1)*(H2O2)*(1)
My approach has involved converting everything to a string, assigning numerical values to those strings, filtering the data depending on if the variable is in a select column, and then multiplying those column together, and then converting to a formula.
#Set the Reaction variable equal to the Rate Constant.
for (i in seq(nrow(df2))) assign(df2$Reaction[i],df2$Rate[i])
#Drop Rate from main data frame
df2 <- df2 %>% mutate(Rate= NULL)
#Find the unique chemical species
# Drop all numbers and constnats
Species <- df2 %>% mutate(
Rate = NULL, R1c = NULL, R2c = NULL, R3c = NULL, P1c = NULL, P2c = NULL, P3c = NULL, Reaction = NULL)
#Uniques
Species <- unique(as.data.frame(c(as.matrix(Species))), drop = FALSE)
names(Species) <- "Species"
# Omit N/A and unknowns
Species <- filter(Species, Species != "unknown")
Species <- na.omit(Species)
# create new variable for each unique species for deltatime Step
Species <- Species %>% mutate(
DeltaSpecies = paste0("d", as.character(Species),sep=""))
#Multiply Each Equation
nms <- grep("^R|^Reaction$|c$", names(df2), value = TRUE)
nms2 <- grep("^R|^Reaction$", names(df2), value = TRUE)
Prod <- function(x) paste(sub("^(.*[[:punct:]].*)", "`\\1`", na.omit(x)), collapse = "*") # if the string contains, begins, ends with a $,-,+ then put it in ' '
#Match Products and Reactants
Products <- df2 %>% filter_at(vars(P1,P2,P3,P1c,P2c,P3c), any_vars(. %in% as.character(Species$Species[[16]])))
Reactants <- df2 %>% filter_at(vars(R1,R2,R3,R1c,R2c,R3c), any_vars(. %in% as.character(Species$Species[[16]])))
Reactants_final <- paste(apply(Reactants[nms2], 1, Prod), collapse = " - ")
Products_final <- paste(apply(Products[nms], 1, Prod), collapse = " + ")
Combine <- paste(Products_final, Reactants_final, sep = " - ")
Formula <- as.formula(paste(Species$DeltaSpecies[[16]], Combine, sep = " ~ "))
I am falling short on how to conditionally make the product expression without using unnecessary variables, assigning values to strings/variables, and extracting a usable formula with variables in the form dX <- a*X + Y*Z
to use in an ODE solver. I understand this is a long winded question, but I am just interested in tips to point me in the right direction to approach the problem (including exploring new functions). Would eval(parse
be an approach to the problem to convert strings to variables, and assign values to them?
来源:https://stackoverflow.com/questions/58107163/using-dplyr-and-conditional-formatting-to-construct-an-ordinary-differential-equ