So I am taking a course that requires learning R and I am struggling with one of the questions:
In this question, you will practice calling one function from within another function. We will estimate the probability of rolling two sixes by simulating dice throws. (The correct probability to four decimal places is 0.0278, or 1 in 36).
(1) Create a function roll.dice() that takes a number ndice and returns the result of rolling ndice number of dice. These are six-sided dice that can return numbers between 1 and 6. For example roll.dice(ndice=2) might return 4 6. Use the sample() function, paying attention to the replace option.
(2) Now create a function prob.sixes() with parameter nsamples, that first sets j equal to 0, and then calls roll.dice() multiple times (nsample number of times). Every time that roll.dice() returns two sixes, add one to j. Then return the probability of throwing two sixes, which is j divided by nsamples.
I am fine with part one, or at least I think so, so this is what I have
roll.dice<-function(ndice)
{
roll<-sample(1:6,ndice,TRUE)
return(roll)
}
roll.dice(ndice=2)
but I am struggling with part two. This is what I have so far:
prob.sixes<-function(nsamples) {
j<-vector
j<-0
roll.dice(nsamples)
if (roll.dice==6) {
j<-j+1
return(j)
}
}
prob.sixes(nsamples=3)
Sorry for all the text, but can anybody help me?
Your code has a couple of problems that I can see. The first one is the interpretation of the question. The question says:
Now create a function prob.sixes() with parameter nsamples, that first sets j equal to 0, and then calls roll.dice() multiple times (nsample number of times).
Check on your code, are you doing this? Or are you calling roll.dice() a single time? Look for ways to do the same thing (in your case, roll.dice) several times; you may consider the function for. Also, here, you need to store the result of this function on a variable, something like
rolled = roll.dice(2)
Second problem:
Every time that roll.dice() returns two sixes, add one to j.
You are checking if roll.dice==6. But this has two problems. First, roll.dice is a function, not a variable. So it will never be equal to 6. Also, you don't want to check if this variable is equal to six. You should ask whether this variable is equal to a pair of sixes. How can you write "a pair of sixes"?
Related
I'm creating a Monte Carlo model using R. My model creates matrices that are filled with either zeros or values that fall within the constraints. I'm running a couple hundred thousand n values thru my model, and I want to find the average of the non zero matrices that I've created. I'm guessing I can do something in the last section.
Thanks for the help!
Code:
n<-252500
PaidLoss_1<-numeric(n)
PaidLoss_2<-numeric(n)
PaidLoss_3<-numeric(n)
PaidLoss_4<-numeric(n)
PaidLoss_5<-numeric(n)
PaidLoss_6<-numeric(n)
PaidLoss_7<-numeric(n)
PaidLoss_8<-numeric(n)
PaidLoss_9<-numeric(n)
for(i in 1:n){
claim_type<-rmultinom(1,1,c(0.00166439057698873, 0.000810856947763742, 0.00183509730283373, 0.000725503584841243, 0.00405428473881871, 0.00725503584841243, 0.0100290201433936, 0.00529190850119495, 0.0103277569136224, 0.0096449300102424, 0.00375554796858996, 0.00806589279617617, 0.00776715602594742, 0.000768180266302492, 0.00405428473881871, 0.00226186411744623, 0.00354216456128371, 0.00277398429498122, 0.000682826903379993))
claim_type<-which(claim_type==1)
claim_Amanda<-runif(1, min=34115, max=2158707.51)
claim_Bob<-runif(1, min=16443, max=413150.50)
claim_Claire<-runif(1, min=30607.50, max=1341330.97)
claim_Doug<-runif(1, min=17554.20, max=969871)
if(claim_type==1){PaidLoss_1[i]<-1*claim_Amanda}
if(claim_type==2){PaidLoss_2[i]<-0*claim_Amanda}
if(claim_type==3){PaidLoss_3[i]<-1* claim_Bob}
if(claim_type==4){PaidLoss_4[i]<-0* claim_Bob}
if(claim_type==5){PaidLoss_5[i]<-1* claim_Claire}
if(claim_type==6){PaidLoss_6[i]<-0* claim_Claire}
}
PaidLoss1<-sum(PaidLoss_1)/2525
PaidLoss3<-sum(PaidLoss_3)/2525
PaidLoss5<-sum(PaidLoss_5)/2525
PaidLoss7<-sum(PaidLoss_7)/2525
partial output of my numeric matrix
First, let me make sure I've wrapped my head around what you want to do: you have several columns -- in your example, PaidLoss_1, ..., PaidLoss_9, which have many entries. Some of these entries are 0, and you'd like to take the average (within each column) of the entries that are not zero. Did I get that right?
If so:
Comment 1: At the very end of your code, you might want to avoid using sum and dividing by a number to get the mean you want. It obviously works, but it opens you up to a risk: if you ever change the value of n at the top, then in the best case scenario you have to edit several lines down below, and in the worst case scenario you forget to do that. So, I'd suggest something more like mean(PaidLoss_1) to get your mean.
Right now, you have n as 252500, and your denominator at the end is 2525, which has the effect of inflating your mean by a factor of 100. Maybe that's what you wanted; if so, I'd recommend mean(PaidLoss_1) * 100 for the same reasons as above.
Comment 2: You can do what you want via subsetting. Take a smaller example as a demonstration:
test <- c(10, 0, 10, 0, 10, 0)
mean(test) # gives 5
test!=0 # a vector of TRUE/FALSE for which are nonzero
test[test!=0] # the subset of test which we found to be nonzero
mean(test[test!=0]) # gives 10, the average of the nonzero entries
The middle three lines are just for demonstration; the only necessary lines to do what you want are the first (to declare the vector) and the last (to get the mean). So your code should be something like PaidLoss1 <- mean(PaidLoss_1[PaidLoss_1 != 0]), or perhaps that times 100.
Comment 3: You might consider organizing your stuff into a dataframe. Instead of typing PaidLoss_1, PaidLoss_2, etc., it might make sense to organize all this PaidLoss stuff into a matrix. You could then access elements of the matrix with [ , ] indexing. This would be useful because it would clean up some of the code and prevent you from having to type lots of things; you could also then make use of things like the apply() family of functions to save you from having to type the same commands over and over for different columns (such as the mean). You could also use a dataframe or something else to organize it, but having some structure would make your life easier.
(And to be super clear, your code is exactly what my code looked like when I first started writing in R. You can decide if it's worth pursuing some of that optimization; it probably just depends how much time you plan to eventually spend in R.)
deadcheck<-function(a,t){ #function to check if dead for specific age at a time age sending to function
roe<-which( birthmort$age[i]==fertmortc$min & fertmortc$max) #checks row in fertmortc(hart) to pick an age that meets min and max age requirements I think this could be wrong...
prob<-1-(((1-fertmortc$mortality[roe])^(1/365))^t) #finds the prob for the row that meets the above requirements
if(runif(1,0,1)<=prob) {d<-TRUE} else {d<-FALSE} #I have a row that has the probability of death every 7 days.
return(d) #outputs if dead
Background: I am creating an agent based model that is a population in a dataframe that is simulating how Tuberculosis spreads in a population. ( I know that there are probably 10000 better ways of having done this). I have thus far created a loop that populates my dataframe with people ages etc. I am now trying to create a function that will go to a chart that lists the probability of death per year, based on a age bracket. 0-5,5-10,10-15 etc. (I have math in there b/c I want it to check who lives, dies, makes babies every 7 days). I have a function similar to this that check who is pregnant and it works. However I for the life of me can't figure out why this function is not working. I keep getting the following error.
Error in if (runif(1, 0, 1) <= prob) { : argument is of length zero
I am unsure how to fix this.
I apologize in advanced it this is a dumb question, I have been trying to teach myself to code over the last 4-5 months. If I asked this question in the wrong format or incorrectly then please let me know how to do so correctly.
Value of prob is of length zero. It means
prob = NULL
in this case. Try to print alter your code and add
print(prob)
so you can check partial result.
As you suspected in your comments, the expression
birthmort$age[i]==fertmortc$min & fertmortc$max
is problematic. What this does is evaluate the comparison birthmort$age[i]==fertmortc$min, and then takes the result of that comparison and combines it with fertmortc$max using the and operator. This involves forming the and of a Boolean value and an integer, which is unlikely to make much sense.
Just guessing, you perhaps want:
birthmort$age[i] >= fertmortc$min & birthmort$age[i] <= fertmortc$max
I don't know if this will fix your problem -- you haven't given enough to test it. For optimal help, you should give a reproducible example. See this for how to do so in R
I am totally new to R. Hopefully you can help. I am trying to simulate from a Hawkes process using R. The main idea is that-first of all I simulated some events from a homogeneous Poisson process. Then each of these events will create their own children using a non homogeneous Poisson process. The code is like as below:
SimulateHawkesprocess<-function(n,tmax,lambda,lambda2){
times<-Simulatehomogeneousprocess(n,lambda)
count<-1
while(count<n){
newevent<-times[count] + Simulateinhomogeneousprocess(lambda2,tmax,lambdamax=NA)
times<-c(times,newevent)
count<-count+1
n<-length(times)
}
return(times)
}
But the r code is producing this infinite loop(probably because of the last line: (n<-length(times))). How can I overcome this problem? How can I put a stopping condition?
This is not a R specific problem. You need to get your algorithm working correctly first. Compare the code you have written against what you want to do. If you need help with the algorithm then tag the question as such. Moreover the function call to Simulateinhomogeneousprocess is very inconsistent. Some insight into that function would help. What is that function returning, a number or a vector?
Within the loop you are increasing the value of n by at least 1 each time so you never reach the end.
newevent<-times[count] + Simulateinhomogeneousprocess(lambda2,tmax,lambdamax=NA)
This creates a non empty variable
times<-c(times,newevent)
Increases the "times" vector by at least 1 (since newevent is non-empty)
count<-count+1
n<-length(times)
You increase the count by 1 but also increase the n value by atleast 1 thus creating a never ending loop. One of these things has to change for the loop to stop.
I have a problem going out of basic programming towards more sophisticated. Could you help me to adjust this code?
There are two vectors with dates and times, one is when activities happens, and another one - when triggers appear. The aim is to find nearest activities date/time to each of triggers, after each trigger happen. Final result is average of all differences.
I have this code. It works. But it's very slow when working with large dataset.
time_activities<- as.POSIXct(c("2008-09-14 22:15:14","2008-09-15 09:05:14","2008-09-16 14:05:14","2008-09-17 12:05:14"), , "%Y-%m-%d %H:%M:%S")
time_triggers<- as.POSIXct(c("2008-09-15 06:05:14","2008-09-17 12:05:13"), , "%Y-%m-%d %H:%M:%S")
for (j in 1:length(time_triggers))
{
for(i in 1:length(time_activities))
{
if(time_triggers[j]<time_activities[i])
{
result[j] = ceiling(difftime(time_activities[i], time_triggers[j], units = 'mins'))
break
}
}
}
print(mean(as.numeric(result)))
Can I somehow get rid of the loop, and do everything with vectors? Maybe you can give me some hint of which function I could use to compare dates at once?
delay=sapply(time_triggers,function(x) max(subset(difftime(x,time_activities,units='mins'),difftime(x,time_activities,units='mins')<0)))
mean(delay[is.finite(delay)])
This should do the trick. As always, the apply family of functions is a good replacement for a for loop.
This gives the average number of minutes that an activity occurred after a trigger.
If you want to see what the activity delay was after each trigger (rather than just the mean of all the triggers), you can just remove the mean() at the beginning. The values will then correspond to each value in time_triggers.
UPDATE:
I updated the code to ignore Inf values as requested. Sadly, this means the code should be 2 lines rather than 1. If you really want, you can make this all one line, but then you will be doing the majority of the computation twice (not very efficient).
I wrote a function in R - called "filtre": it takes a dataframe, and for each line it says whether it should go in say bin 1 or 2. At the end, we have two data frames that sum up to the original input, and corresponding respectively to all lines thrown in either bin 1 or 2. These two sets of bin 1 and 2 are referred to as filtre1 and filtre2. For convenience the values of filtre1 and filtre2 are calculated but not returned, because it is an intermediary thing in a bigger process (plus they are quite big data frame). I have the following issue:
(i) When I later on want to use filtre1 (or filtre2), they simply don't show up... like if their value was stuck within the function, and would not be recognised elsewhere - which would oblige me to copy the whole function every time I feel like using it - quite painful and heavy.
I suspect this is a rather simple thing, but I did search on the web and did not find the answer really (I was not sure of best key words). Sorry for any inconvenience.
Thxs / g.
It's pretty hard to know the optimum way of achieve what you want as you do not provide proper example, but I'll give it a try. If your variables filtre1 and filtre2 are defined inside of your function and you do not return them, of course they do not show up on your environment. But you could just return the classification and make filtre1 and filtre2 afterwards:
#example data
df<-data.frame(id=1:20,x=sample(1:20,20,replace=TRUE))
filtre<-function(df){
#example function, this could of course be done by bins<-df$x<10
bins<-numeric(nrow(df))
for(i in 1:nrow(df))
if(df$x<10)
bins[i]<-1
return(bins)
}
bins<-filtre(df)
filtre1<-df[bins==1,]
filtre2<-df[bins==0,]