I'm trying to create a function that simulate dolling m dice, n times, calculate the minimum of the outcome of the dice in each roll and then calculate the mean of the minimum and store the values into a vector.
mindice = function(n = 10, m = 3)
{
v <- vector
for(i in 1:10)
{
minima= numeric(n)
for(i in 1:n)
{
minima[i] = min(sample(6,m,replace=T))
}
v[i] = mean(minima)
}
v
}
I'm calling the function like that: mindice()
and the output is: Error in v[i] <- mean(minima) : object of type 'closure' is not subsettable
any help will be appreciated
I don't know if this fits your expectations. This function returns both the vector for the minimum per roll and their average
mindice <- function(n = 10, m = 3)
{
minima <- vector("numeric")
for(i in 1:n){
minima = c(minima, min(sample(6,m,replace=T)))
}
list(minimum_values=minima,
mean_minima=mean(minima))
}
mindice()
The comment about using v = vector() rather than v = vector should solve the bug in the way you've written the function. If you're interested in a more R-like way to do this function, try this:
mindice2 = function(n = 10, m = 3) {
rolls = sample(6, size = m * n, replace = TRUE)
rolls = matrix(rolls, nrow = m)
minima = apply(rolls, MARGIN = 2, FUN = min)
cum_mean = cumsum(minima) / seq_along(minima)
return(cum_mean)
}
Rather than sampling each roll separately, we do all the rolls at once (more efficient), and then put them in a matrix where each column is a roll of m dice. We can then use apply to find the minima, and cumsum to calculate the mean minimum after each roll.
Related
I am working on data replacement in a matrix. The replaced data will be calculated by calculating the sd of the (1+2k)X(1+2k) matrix centered on the value.
replace.loop = function(n, m, k, pad){
#search the value row by row, column by column
for (i in n) {
for (j in m) {
pad[i,j] = sd(as.vector(pad[(i-k):(i+k),(j-k):(j+k)]))
}
}
return(pad) #return the matrix that finishing calculation
}
Is there any way to rewrite this function with any apply() function? I am an R starter learner, so I am not sure which apply() function I should use.
for example:
X = matrix(c(.5,.5,.4,.4,.3,.5,.5,.4,.3,.3,.4,.4,.3,.2,.2,.4,.4,.3,.2,.1,.3,.3,.2,.2,.1), ncol=5)
k = 1
pad.X = matrix(0, dim(X)[1]+2*k, dim(X)[2]+2*k)
n = (k+1):(dim(X)[1]+k); m = (k+1):(dim(X)[2]+k)
pad.X[n, m] = X
Thanks!
I created a copy of pad called padOut. mapply will return the results as a matrix, which you can then assign to the relevant portion of padOut using matrix indexing:
replace.apply = function(n, m, k, pad){
kk <- -k:k
idx <- expand.grid(n, m)
padOut <- pad
padOut[as.matrix(idx)] <- mapply(function(i) sd(pad[idx[i,1] + kk, idx[i, 2] + kk]), 1:(length(m)*length(n)))
return(padOut)
}
With your example data:
X = matrix(c(.5,.5,.4,.4,.3,.5,.5,.4,.3,.3,.4,.4,.3,.2,.2,.4,.4,.3,.2,.1,.3,.3,.2,.2,.1), ncol=5)
k = 1
pad.X = matrix(0, dim(X)[1]+2*k, dim(X)[2]+2*k)
n = (k+1):(dim(X)[1]+k); m = (k+1):(dim(X)[2]+k)
pad.X[n, m] = X
replace.loop = function(n, m, k, pad){
#search the value row by row, column by column
padOut <- pad
for (i in n) {
for (j in m) {
padOut[i,j] = sd(as.vector(pad[(i-k):(i+k),(j-k):(j+k)]))
}
}
return(padOut) #return the matrix that finishing calculation
}
pad1 <- replace.loop(n, m, k, pad.X)
pad2 <- replace.apply(n, m, k, pad.X)
identical(pad1, pad2)
#> [1] TRUE
I know I can use expand.grid for this, but I am trying to learn actual programming. My goal is to take what I have below and use a recursion to get all 2^n binary sequences of length n.
I can do this for n = 1, but I don't understand how I would use the same function in a recursive way to get the answer for higher dimensions.
Here is for n = 1:
binseq <- function(n){
binmat <- matrix(nrow = 2^n, ncol = n)
r <- 0 #row counter
for (i in 0:1) {
r <- r + 1
binmat[r,] <- i
}
return(binmat)
}
I know I have to use probably a cbind in the return statement. My intuition says the return statement should be something like cbind(binseq(n-1), binseq(n)). But, honestly, I'm completely lost at this point.
The desired output should basically recursively produce this for n = 3:
binmat <- matrix(nrow = 8, ncol = 3)
r <- 0 # current row of binmat
for (i in 0:1) {
for (j in 0:1) {
for (k in 0:1) {
r <- r + 1
binmat[r,] <- c(i, j, k)}
}
}
binmat
It should just be a matrix as binmat is being filled recursively.
I quickly wrote this function to generate all N^K permutations of length K for given N characters. Hope it will be useful.
gen_perm <- function(str=c(""), lst=5, levels = c("0", "1", "2")){
if (nchar(str) == lst){
cat(str, "\n")
return(invisible(NULL))
}
for (i in levels){
gen_perm(str = paste0(str,i), lst=lst, levels=levels)
}
}
# sample call
gen_perm(lst = 3, levels = c("x", "T", "a"))
I will return to your problem when I get more time.
UPDATE
I modified the code above to work for your problem. Note that the matrix being populated lives in the global environment. The function also uses the tmp variable to pass rows to the global environment. This was the easiest way for me to solve the problem. Perhaps, there are other ways.
levels <- c(0,1)
nc <- 3
m <- matrix(numeric(0), ncol = nc)
gen_perm <- function(row=numeric(), lst=nc, levels = levels){
if (length(row) == lst){
assign("tmp", row, .GlobalEnv)
with(.GlobalEnv, {m <- rbind(m, tmp); rownames(m) <- NULL})
return(invisible(NULL))
}
for (i in levels){
gen_perm(row=c(row,i), lst=lst, levels=levels)
}
}
gen_perm(lst=nc, levels=levels)
UPDATE 2
To get the expected output you provided, run
m <- matrix(numeric(0), ncol = 3)
gen_perm(lst = 3, levels = c(0,1))
m
levels specifies a range of values to generate (binary in our case) to generate permutations, m is an empty matrix to fill up, gen_perm generates rows and adds them to the matrix m, lst is a length of the permutation (matches the number of columns in the matrix).
s <- seq(-10, 6, by = 0.1)
my.fun = function(s)
{
n = length(s)
s = 0
for(i in 1:n)
{
s = ((s[i]*s[i]*s[i]*s[i])*sin(1/s[i]) +(s[i]*s[i]))/(1+abs((s[i]*s[i]*s[i])))
}
s
}
This is my function. I am attempting to compute a sequence of numbers and then use that sequence within the equation. However, It isnt saving the new variable S and the function wont print anything out either.
Two reasons:
You're setting s to zero in your function
The main guts of your function contains 1/s[i], so s shouldn't contain any zeroes.
Try
s <- seq(-10, 6, by = 0.1)
s = s[which(s != 0)] # to drop the zero from the vector
my.fun = function(s)
{
n = length(s)
for(i in 1:n) {
s[i] = ((s[i]*s[i]*s[i]*s[i])*sin(1/s[i]) + s[i]*s[i]))/(1+abs((s[i]*s[i]*s[i])))
}
s
}
my.fun(s)
You cant return an output in the definition of a function itself.
Do my.fun(s) to return the output for s.
Also make sure to not have 0s while initializing values for s. Since you are doing 1/s at one point, you will return only NaNs.
I would like to have a vector res with length 200, which includes 20 times repetition of random generation values divided by 2 which is r[i], how can I get this in R?I wrote the following code but it is just save each iteration values,not the whole iterations.
r = rep(0, 10)
res = matrix(0, nrow=200, ncol=1)
for(j in 1:20){
for(i in 1:10){
x = rnorm(10, 0, 1)
r[i] = x/2
}
res = rbind(r)
}
as Roland said in a comment to your question writing two loops for this isn't a good practice. However, you can do it like this
res = rep(0, 200)
r = rep(0, 10)
for(j in 1:20){
for(i in 1:10){
x = rnorm(1, 0, 1)
r[i] = x/2
}
res[((j-1)*10+1):(j*10)] = r
}
As for your solution, there were some problems:
There is no need to define a matrix res = matrix(0, nrow=200, ncol=1) if you only need a vector
rnorm(10,0,1) returns a vector of 10 values so assigning it to r[i] (which takes only one value) isn't correct
rbind is used to connect two vectors/matrices/... by rows so using it with only one parameter doesn't really make a sense here
i´d like to assign factors representing quantiles. Thus I need them to be numeric.
That´s why I wrote the following function, which is basically the answer to my problem:
qdum <- function(v,q){
qd = quantile(v,1:(q)/q)
v = as.data.frame(v)
v$b = 0
names(v) <- c("a","b")
i=1
for (i in 1:q){
if(i == 1)
v$b[ v$a < qd[1]] = 1
else
v$b[v$a > qd[i-1] & v$a <= qd[i]] = i
}
all = list(qd,v)
return(all)
}
you may laugh now :) .
The returned list contains a variable that can be used to assign every observation to its corresponding quantile. My question is now: is there a better way (more "native" or "core") to do it? I know about quantcut (from the gtools package), but at least with the parameters I got, I ended up with only with those unhandy(? - at least to me) thresholds.
Any feedback thats helps to get better is appreciated!
With base R, use quantiles to figure out the splits and then cut to convert the numeric variable to discrete:
qcut <- function(x, n) {
cut(x, quantile(x, seq(0, 1, length = n + 1)), labels = seq_len(n),
include.lowest = TRUE)
}
or if you just want the number:
qcut2 <- function(x, n) {
findInterval(x, quantile(x, seq(0, 1, length = n + 1)), all.inside = T)
}
I'm not sure what quantcut is but I would do the following
qdum <- function(v, q) {
library(Hmisc)
quantilenum <- cut2(v, g=q)
levels(quantilenum) <- 1:q
cbind(v, quantilenum)
}