use of curly brackets within replicate function in R - r

B <- 10000
results <- replicate(B, {
hand <- sample(hands1, 2)
(hand[1] %in% aces & hand[2] %in% facecard) | (hand[2] %in% aces & hand[1] %in% facecard)
})
mean(results)
this piece of code works perfectly and do the desired thi
this is a monte carlo simulation. I don't understand the way they put curly brackets {} in the replicate function. i can understand the function of that code but i cant understand the way they put the code.

The reason is that we have multiple expressions
hand <- sample(hands1, 2)
is the first expression and the second is
(hand[1] %in% aces & hand[2] %in% facecard) | (hand[2] %in% aces & hand[1] %in% facecard)
i.e. if there is only a single expression, we don't need to block with {}
It is a general case and not related to replicate i.e. if we use a for loop with a single expression, it doesn't need any {}
for(i in 1:5)
print(i)
and similarly, something like if/else
n <- 5
if(n == 5)
print(n)
It is only needed when we need more than one expression

Related

R - Flexible conditions

I have the folowing R statement. Basically it goes through the entire matchesData data frame and checks if the conditions are matched for each row.
If it matches, put a '1' at matchesData$isRedPreferredLineup.
matchesData$isRedPreferredLineup <- ifelse((matchesData$redTop==red_poplist[1] &
matchesData$redADC==red_poplist[2] &
matchesData$redJungle==red_poplist[3] &
matchesData$redSupport==red_poplist[4] &
matchesData$redMiddle==red_poplist[5] &
matchesData$YearSeason==Season), 1,
matchesData$isRedPreferredLineup)
However, now I need the condition to be flexible. Meaning, if
matchesData$redTop==red_poplist[1]
matchesData$redADC==red_poplist[2]
matchesData$redJungle==red_poplist[3]
conditions are matched, or if
matchesData$redJungle==red_poplist[3]
matchesData$redSupport==red_poplist[4]
matchesData$redMiddle==red_poplist[5]
conditions are matched, or any other permutation comprising 3 or more of the following conditions are matched, I would like to put '1' at matchesData$isRedPreferredLineup.
(matchesData$redTop==red_poplist[1] &
matchesData$redADC==red_poplist[2] &
matchesData$redJungle==red_poplist[3] &
matchesData$redSupport==red_poplist[4] &
matchesData$redMiddle==red_poplist[5] &
matchesData$YearSeason==Season)
How can I do so in a vectorized ifelse statement like this?
Or is there a better way to do this?
Please bear with me, I am pretty new to R. Thanks.
Maybe this coud work:
selectIndex <- apply(matchesData,1,function(row){
sum(c(row['redTop'] == red_poplist[1],
row['redADC'] == red_poplist[2],
row['redJungle'] == red_poplist[3],
row['redSupport'] == red_poplist[4],
row['redMiddle'] == red_poplist[5],
row['YearSeason'] == Season) > 3)
})
matchesData$isRedPreferredLineup[selectIndex] <- 1
You could vectorise the TRUE/FALSE statements like this:
my.conditions <- cbind(matchesData$redTop==red_poplist[1], matchesData$redADC==red_poplist[2],
matchesData$redJungle==red_poplist[3], matchesData$redSupport==red_poplist[4],
matchesData$redMiddle==red_poplist[5], matchesData$YearSeason==Season)
Then you could consider S1 <- rowSums(my.conditions) which will give you the number of TRUEs in my.conditions and then (your final condition would boil down to ifelse(S1 > 2, 1, ...)) consider the following:
matchesData$isRedPreferredLineup[which(S1 > 2)] <- 1

Looping through numerous functions with a vector of characters

I thought this would be easier than it is, but I am learning to code in R so looping is certainly not my strong point.
What I am attempting to do here is take a series of functions that all have a common theme of MISO. As you can see in the first batch of code below MISO is common, but I would like to swap the MISO for i as one would do in a for loop and then loop through a few different names in a character vector. Let's call that character vector ID so that ID <- c("MISO","PJM","SERC")
At this point in the code, all_Cities_MISO is already a data frame in my environment. I just want to break it up and perform some calculations.
meanAvgHighMISO <- mean(all_Cities_MISO$Col21)
meanAvgLowMISO <- mean(all_Cities_MISO$Col20)
meanAvgMISO <- mean(cbind(meanAvgHighMISO,meanAvgLowMISO))
names(meanAvgMISO) <- ifelse(meanAvgMISO<65,"HDD","CDD")
MISO_Avg_DD <- ifelse(meanAvgMISO<65,(65-meanAvgMISO),(meanAvgMISO-65)) #average degree days for each period
MISO_op_mean <- apply(all_Cities_MISO[,1:19],2, mean)
So I attempted this a few different times, but keep getting errors like Error: unexpected string constant in:
" meanAvgHigh"i""
I feel like it should be simple to replace the MISO with a PJM throughout the code above with a simple for loop, but no luck. It must be something with it not liking MISO as a character.
Here is my attempt at the for loop:
ID <- c("MISO","PJM","SERC")
for(i in ID){
meanAvgHigh"i" <- mean(all_Cities_"i"$Col21)
meanAvgLow"i" <- mean(all_Cities_"i"$Col20)
meanAvg"i" <- mean(cbind(meanAvgHigh"i",meanAvgLow"i"))
names(meanAvg"i") <- ifelse(meanAvg"i"<65,"HDD","CDD")
"i"_Avg_DD <- ifelse(meanAvg"i"<65,(65-meanAvg"i"),(meanAvg"i"-65)) #average degree days for each period
"i"_op_mean <- apply(all_Cities_"i"[,1:19],2, mean)
}
I attempted using [i] instead of "i", but that didn't work either. I understand that MISO itself in the first code I displayed is not a character, but I'm not sure how R would recognize it in the loop otherwise... I just would like to do a simple swap of names in a loop. MISO for PJM or for SERC etc etc.
Any help is greatly appreciated, thank you.
While you can do that by using the environment() and assign() methods, I would advise against it. You should instead use a nested list to save those values.
However, for completeness, this is how I think one would do it (untested):
env <- environment()
ID <- c("MISO","PJM","SERC")
for(i in ID){
assign(paste0("meanAvgHigh", i), mean(env[[ paste0("all_Cities_", i) ]]$Col21))
assign(paste0("meanAvgLow", i), mean(env[[ paste0("all_Cities_", i) ]]$Col20))
assign(paste0("meanAvg", i), mean(cbind(env[[ paste0("meanAvgHigh", i) ]], env[[ paste0("meanAvgLow", i) ]])))
names(env[[ paste0("meanAvg", i) ]]) <- ifelse(env[[ paste0("meanAvg", i) ]] < 65,"HDD","CDD")
##### Note: The ifelse can probably be replaced by an abs
assign(paste0(i, "_Avg_DD"), ifelse( env[[ paste0("meanAvg", i) < 65,
(65 - env[[ paste0("meanAvg", i) ]]),
(env[[ paste0("meanAvg", i) ]] - 65)
)) #average degree days for each period
assign(paste0(i, "_op_mean"), apply(env[[ paste0("all_Cities_", i) ]][,1:19], 2, mean)
}
The basic idea is using assign to set the values in the current environment and then using the current environment env to get them via indexing.

Conditional statement in daa.R of the R "matchingMarkets" library

I am trying to get my head around daa.R, one of the functions in the matchingMarkets R library (links are to GitHub repositories). On lines 134-135, one finds the following if statement
if (0 %in% (c.hist[[j]] & any(c.prefs[ ,j]==proposers[k]))){ # if no history and proposer is on preference list
c.hist[[j]][c.hist[[j]]==0][1] <- proposers[k] # then accept
}
where c.hist and proposers are a list and c.prefs a matrix.
I am puzzled by the parentheses in the conditional statement. Instead of the above synthax, I would have opted for
if (0 %in% c.hist[[j]] & any(c.prefs[ ,j]==proposers[k]))
I don't understand how the original condition may work. How could R possibly check whether 0 is in (c.hist[[j]] & any(c.prefs[ ,j]==proposers[k]))?
I am a beginner in R, so I wanted to make sure I was not missing something and tried to replicate a similar synthax with other conditions such as,
> x = list(4,3)
> y = list(5,2)
> if (3 %in% (x & any(y == 5))){z = 8}
As I expected, I got an error message
Error in x & any(y == 5) : operations are possible only for numeric, logical or complex types
whereas things go just fine when I write
if (3 %in% x & any(y == 5)){z = 8}
instead.
What am I missing? Why would the kind of conditional synthax I am puzzled by work in daa.R and not with the other conditions I tried?
When you ask R if 0 %in% x where x is a logical vector, R will first convert x to a numeric vector where FALSE becomes 0 and TRUE becomes 1. So essentially, asking if 0 %in% x is like asking if x contains any FALSE. This is arguably pretty bad practice. A better approach would be to test if any(!x) or !all(x). Worse, if x has length 1 as it seems to be the case here, you would just test if !x.
In light of the contorted usage, you are raising a very good question: is the code doing what it really meant to do? In R, the %in% operator has higher precedence than & (see ?Syntax), thus these two statements are not the same:
0 %in% (c.hist[[j]]) & any(c.prefs[ ,j]==proposers[k])) # original code
0 %in% c.hist[[j]] & any(c.prefs[ ,j]==proposers[k]) # what you suggested
and we would need to look closely at what the code is supposed to be doing to decide if it is correct or wrong. I will just point out that you did not test your assumption properly: the error you got ("unexpected '{'") is because you forgot a closing parenthesis:
if (3 %in% (x & any(y == 5)){z = 8}
should be
if (3 %in% (x & any(y == 5))){z = 8}

if function and length of the logical vector

I have a dataframe where the dates are given as hydrological years (October to September). To change this I am trying to use a if statement:
if(cet$month== 10|cet$month==11|cet$month==12)
cet$year <- substr(as.character(cet[,2]),1,4) else
cet$year <- substr(as.character(cet[,2]),6,9)
but I get an error:
the condition has length > 1 and only the first element will be used
Reading the "if" help file I realized that the condition has to be a length-one logical vector. Is there no way of using an "or" with an "if"? All I want is to apply that expression if the month is October, November or December.
ifelse is the vectorised version. You can also use %in% to reduce the number of statements.
cet$year <- ifelse(cet$month%in%(10:12), substr(as.character(cet[,2]),1,4), substr(as.character(cet[,2]),6,9))
Ok, here's a reproducible example that should help to clarify things:
# generate some vector
x <- c(1,2,4,4,5,5,6,6,6)
# have a check using OR, return values
x[x == 2 | x == 1]
## or return TRUE / FALSE
(x == 2 | x == 1)
or check ?ifelse
EDIT: Note that for characters you need to use "", like x == "yourchars" | x == "someotherchars"
Here's also some simple reference and how to work with operators: QuickR
the OR instruction is double pipes
| => || in the if()

multiple bquote items in legend of an R plot

Following works, (copy & paste into R)
a=123
plot(1,1)
legend('bottomleft',legend=bquote(theta == .(a)))
I want to have multiple items in the legend.
All with greek letters.
As a simple example, if I repeat the item twice the code does not work anymore
a=123
plot(1,1)
legend('bottomleft',legend=c(bquote(theta == .(a)),bquote(theta == .(a))))
I have tried many more complicated expressions but they all did not work.
Any help will be appreciated.
In this case, plotmath is not able to coerce the list of calls to expressions.
> cs <- c(bquote(theta == .(a)),bquote(theta == .(a)))
> cs
[[1]]
theta == 123
[[2]]
theta == 123
> sapply(cs, class)
[1] "call" "call"
You can make this work if you coerce to expressions yourself:
> c(as.expression(bquote(theta == .(a))), as.expression(bquote(theta == .(a))))
expression(theta == 123, theta == 123)
> plot(1,1)
> legend('bottomleft',legend= c(as.expression(bquote(theta == .(a))),
+ as.expression(bquote(theta == .(a)))))
Another way is to coerce the original list of calls to expressions using sapply:
plot(1,1)
legend("bottomleft",
sapply(c(bquote(theta == .(a)), bquote(theta == .(a))), as.expression))
To coerce the original list of calls to expressions it is not necessary to use sapply(). It suffices to use as.expression() only for one of the components within the c() construct:
plot(1,1)
legend("bottomleft",
c(as.expression(bquote(theta == .(a))), bquote(theta == .(a))))
c() will then automatically coerce the whole list, to the expression class.

Resources