I am trying to make a simple for loop, that would add a new column to the existing data frame, by assigning a time class to each observation. I am getting 'object 'i' not found' and not sure where is a mistake. I am not that experienced with R, so thank you for any help!
for (i in 1:nrow(my.data)) {
if(my.data$RTime[i] <= 3600){
my.data$RTimeHour[i] <- 1
}ifelse (my.data$RTime[i] > 3601 & my.data$RTime[i] < 7200){
my.data$RTimeHour[i] <- 2
}esle {
my.data$RTimeHour[i] <- 3
}
}
I think you can simply use a nested ifelse statement:
my.data$RTimeHour <- ifelse(my.data$RTime <= 3600, 1,
ifelse(my.data$RTime > 3600 & my.data$RTime <= 7200, 2, 3))
The error is probably coming from the ifelse() you have:
for (i in 1:nrow(my.data)) {
if(my.data$RTime[i] <= 3600){
my.data$RTimeHour[i] <- 1
}ifelse (my.data$RTime[i] > 3601 & my.data$RTime[i] < 7200){
my.data$RTimeHour[i] <- 2
}esle {
my.data$RTimeHour[i] <- 3
}
}
Try this instead:
if(my.data$RTime[i] <= 3600){
my.data$RTimeHour[i] <- 1
}else if(my.data$RTime[i] > 3601 & my.data$RTime[i] < 7200){
my.data$RTimeHour[i] <- 2
}else {
my.data$RTimeHour[i] <- 3
}
}
ifelse vectorizes how the problem, so ifelse(x[i]) will try to refer to something outside of the loop.
Vectorized with tidyverse we can just do:
library(tidyverse)
my.data %>% mutate(RTimeHour = case_when(
RTime <= 3600 ~ 1,
RTime < 7200 ~ 2,
TRUE ~ 3)
)
Related
I have the below existing code in R. The code prints the next immediate prime number. I want to consider inclusive of starting number
np <- function(x){
if (x==1L | x==2L) {return(2L)}
else {
temp <- x+1
test <- 2:x
while( any( (temp %% test) == 0 ) ){
temp <- temp+1
}
temp
} }
Eg.. np(7) returns 11. But expected output is 7.
Try the code below (following a similar idea in the answer here)
np <- function(x) {
p <- x
repeat {
if (p %in% c(2, 3) | all(p %% ceiling(sqrt(2:p)) != 0)) {
return(p)
}
p <- p + 1
}
}
and you will see
> np(2)
[1] 2
> np(3)
[1] 3
> np(4)
[1] 5
> np(5)
[1] 5
> np(7)
[1] 7
Maybe it's stupid but does this do the trip?
np <- function(x){
if (x==1L | x==2L) {return(2L)}
else {
x= x-1
temp <- x+1
test <- 2:x
while( any( (temp %% test) == 0 ) ){
temp <- temp+1
}
temp
} }
You are testing numbers above x only by calling temp <- x+1. Here is a version that should work with minimal changes to your code:
np <- function(x){
if (x==1L | x==2L) {return(2L)}
else {
temp <- x
test <- 2:(x - 1)
while( any( (temp %% test) == 0 ) ){
temp <- temp+1
}
temp
} }
here is the code for a simulation I'm trying to run:
n_draws <- 1000
black <- rep(0, n_draws)
hispanic <- rep(0, n_draws)
asian <- rep(0, n_draws)
white <- rep(0, n_draws)
cutoff <- c(0.05,0.1,0.25,1)
draws <- runif(n_draws,0,1)
for (i in draws){
if (draws[i] < cutoff[1]){
black[i] <- 1
} else if ((draws[i] >= cutoff[1]) & (draws[i] < cutoff[2])){
hispanic[i] <- 1
} else if ((draws[i] >= cutoff[2]) & (draws[i] < cutoff[3]){
asian[i] <- 1
} else {
white[i] <- 1
}
}
Basically, I want to add a 1 to the corresponding list, conditional on where that number falls in the range (0,1). I'm not sure why this is giving an error. Suggestions?
You're just missing a closing bracket just after cutoff[3], also used seq_along in my example as it's a bit nicer
for (i in seq_along(draws)){
if (draws[i] < cutoff[1]){
black[i] <- 1
} else if ((draws[i] >= cutoff[1]) & (draws[i] < cutoff[2])){
hispanic[i] <- 1
} else if ((draws[i] >= cutoff[2]) & (draws[i] < cutoff[3])){
asian[i] <- 1
} else {
white[i] <- 1
}
}
I am trying to run this code:
check_zeros <- function(x) { # WIP
if (x == 0) {
!(df[gsub('\\b0+','',format(as.Date(formation$study_start_dates_list[i]),'%m/%d/%Y')), names(x)] == df[gsub('\\b0+','',format(as.Date(formation$study_end_dates_list[i]),'%m/%d/%Y')), names(x)])
}
}
remove_undesired_stocks2 <- function(n) {
i = 1
listofdfs_filtered <- list()
for (i in 1:n) {
a <- subset(average_returns, row.names(average_returns) == i)
b <- as.data.frame(sapply(subset(average_returns, row.names(average_returns) == i), function(x) all(x == 0 | is.nan(x) | check_zeros(x) )))
c <- a[, !b]
listofdfs_filtered[[i]] <- c
}
return(listofdfs_filtered)
}
Error comes out as:
Error in if (x == 0) { : missing value where TRUE/FALSE needed
I think it is bc there is a NaN going into x == 0 of the check_zeros function.
Any how I can overcome this? Thanks in advance.
I think I solved it myself:
the check_zero function is constructed in a way which cannot take objects with length > 1. more specifically logic inside if cannot use objects length > 1.
Since I was using a object with length > 1, there was an error
You should use ifelse in this case:
check_zeros <- function(x) {
ifelse(x == 0, (df[gsub('\\b0+','',format(as.Date(formation$study_start_dates_list[i]),'%m/%d/%Y')), names(x)] == df[gsub('\\b0+','',format(as.Date(formation$study_end_dates_list[i]),'%m/%d/%Y')), names(x)]), FALSE)
}
Cheers.
=if(OR([a]="1",AND([b]<=50,[b]>0)),1,0) - Excel Formula
How Can i Write this as an R code:
below is the code which i tried
i = 1
for (i in 1: length(a))
{
if((dataframe$a[i] == 1) || ((dataframe$b[i] <= 50) && (dataframe$b[i}> 0)))
{dataframe$c[i] <- as.numeric(1);}
else
{dataframe$c[i] <- as.numeric(0);}
}
}
I get the following Errors:
Error: unexpected numeric constant in:
Error: unexpected 'else' in " else
Error: unexpected numeric constant in "
Error: unexpected '}' in "}"
You can try
within(dat, c <- ((0 < b & b <= 50 ) | a == 1) + 0 )
data
set.seed(25)
dat <- data.frame(a=sample(1:5, 100, replace=TRUE),
b= sample(-10:100, 100, replace=TRUE))
There was a "typo" in dataframe$b[i} and one extra }.
So, sample data from #akrun:
set.seed(25)
dat <- data.frame(a=sample(1:5, 100, replace=TRUE),
b= sample(-10:100, 100, replace=TRUE))
Code:
i = 1
for (i in 1: length(dat$a)){
if((dat$a[i] == 1) || ((dat$b[i] <= 50) && (dat$b[i]> 0))){
dat$c[i] <- as.numeric(1)
} else {
dat$c[i] <- as.numeric(0)
}
}
Also works with single operator:
i = 1
for (i in 1: length(dat$a)){
if((dat$a[i] == 1) | ((dat$b[i] <= 50) & (dat$b[i]> 0))){
dat$c[i] <- as.numeric(1)
} else {
dat$c[i] <- as.numeric(0)
}
}
See the diference between single and double operators here
I am trying to generate a random sample that excludes certain "bad data." I do not know whether the data is "bad" until after I sample it. Thus, I need to make a random draw from the population and then test it. If the data is "good" then keep it. If the data is "bad" then randomly draw another and test it. I would like to do this until my sample size reaches 25. Below is a simplified example of my attempt to write a function that does this. Can anyone please tell me what I am missing?
df <- data.frame(NAME=c(rep('Frank',10),rep('Mary',10)), SCORE=rnorm(20))
df
random.sample <- function(x) {
x <- df[sample(nrow(df), 1), ]
if (x$SCORE > 0) return(x)
#if (x$SCORE <= 0) run the function again
}
random.sample(df)
Here is a general use of a while loop:
random.sample <- function(x) {
success <- FALSE
while (!success) {
# do something
i <- sample(nrow(df), 1)
x <- df[sample(nrow(df), 1), ]
# check for success
success <- x$SCORE > 0
}
return(x)
}
An alternative is to use repeat (syntactic sugar for while(TRUE)) and break:
random.sample <- function(x) {
repeat {
# do something
i <- sample(nrow(df), 1)
x <- df[sample(nrow(df), 1), ]
# exit if the condition is met
if (x$SCORE > 0) break
}
return(x)
}
where break makes you exit the repeat block. Alternatively, you could have if (x$SCORE > 0) return(x) to exit the function directly.
use this after your first sample
while (any(bad <- (x$SCORE <= 0)))
x[bad, ] <- df[sample(nrow(df), sum(bad)), ]
You can just select the rows to sample directly like so (just 5):
> df <- data.frame(NAME=c(rep('Frank',10),rep('Mary',10)), SCORE=rnorm(20))
> df[sample(which(df$SCORE>0), 5),]
NAME SCORE
14 Mary 1.0858854
10 Frank 0.7037989
16 Mary 0.7688913
5 Frank 0.2067499
17 Mary 0.4391216
this is without replacement, for bootstrap put in replace=T.
random.sample <- function(x) {
x <- df[sample(nrow(df), 1), ]
if (x$SCORE > 0) return(x)
Recall(x)# run the function again
}
random.sample(df)
# NAME SCORE
#14 Mary 1.252566
It seems to me that this should work as well:
df$SCORE[ df$SCORE > 0 ][ sample(1:sum(df$SCORE > 0), 1) ]
#[1] 0.6579631