Interpreting condition has length 1 warning from `if` function
maybe you want ifelse
:
a <- c(1,1,1,1,0,0,0,0,2,2)
ifelse(a>0,a/sum(a),1)
[1] 0.125 0.125 0.125 0.125 1.000 1.000 1.000 1.000
[9] 0.250 0.250
What does the error the condition has length 1 and only the first element will be used mean?
the problem is that you are using an if-statement with a vector. This is not allowed and doesn't work as you would expect. You can use the case_when
function from dplyr
.
library(dplyr)
split_firstname <- function(full_name){
x <- stringr::str_count(full_name, " ")
case_when(
x == 1 ~ stringr::word(full_name, 1),
x == 2 ~ paste(stringr::word(full_name,1), stringr::word(full_name,2), sep = " "),
x == 4 ~ paste(stringr::word(full_name,1), stringr::word(full_name,2), stringr::word(full_name,3), stringr::word(full_name,4), sep = " ")
)
}
The condition has length 1 and only the first element will be used
You get the error because if
can only evaluate a logical
vector of length 1.
Maybe you miss the difference between &
(|
) and &&
(||
). The shorter version works element-wise and the longer version uses only the first element of each vector, e.g.:
c(TRUE, TRUE) & c(TRUE, FALSE)
# [1] TRUE FALSE
# c(TRUE, TRUE) && c(TRUE, FALSE)
[1] TRUE
You don't need the if
statement at all:
mut1 <- trip$Ref.y=='G' & trip$Variant.y=='T'|trip$Ref.y=='C' & trip$Variant.y=='A'
trip[mut1, "mutType"] <- "G:C to T:A"
What does warning mean: the condition has length 1 and only the first element will be used
This,
paste(df.short$AD, df.short$ED, sep="")
is a vector, not of length 1, so when you pass that to your function, you are testing a vector against a scalar:
nchar(x) == 5
I suggest looping over your function using an apply function, something like
mapply(fixED, x = paste(df.short$AD, df.short$ED, sep=""))
Getting error the condition has length 1 and only the first element will be used when using if else loop
if
and else
should be used on logical conditions that are length 1. You are asking if a vector (OldTimeColumn
) of some length n
is equal to a vector of a single value TRUE
-- so that's why the warning message says what it says, and it only evaluates the first element of OldTimeColumn
by comparing it to TRUE
.
A better way for your particular example might be to use the case_when
structure.
library(dplyr)
library(stringr)
df <- data.frame(
OldTimeColumn = c("12", "1", "2", "3", "4"),
stringsAsFactors = F
)
df <- df %>%
mutate(NewTimeColumn = case_when(
str_detect(OldTimeColumn, "^12") ~ "12",
str_detect(OldTimeColumn, "^1") ~ "1",
str_detect(OldTimeColumn, "^2") ~ "2",
str_detect(OldTimeColumn, "^3") ~ "3",
TRUE ~ "11"
))
df
OldTimeColumn NewTimeColumn
1 12 12
2 1 1
3 2 2
4 3 3
5 4 11
Trying to do this with ifelse
(which does work on evaluating vectors) would be more cumbersome but can be done:
df <- df %>%
mutate(NewTimeColumn = ifelse(str_detect(OldTimeColumn, "^12") == TRUE,
"12", ifelse(str_detect(OldTimeColumn, "^1") == TRUE,
"1", ifelse(str_detect(OldTimeColumn, "^2") == TRUE,
"2", ifelse(str_detect(OldTimeColumn, "^3") == TRUE, "3", "11")))))
“the condition has length 1 and only the first element will be used” warning from nested `if elses' over a dataframe
1) Personally I try to do as much R as I can with only a small subset of its many commands. Maybe a simple apply
is an easier way to manage this. apply
with MARGIN = 1
will give each row pf your data.frame to a function. So I made this slight change to your function (just the first 3 lines are of interest here, the rest is copy&paste):
incidence_headaches<-function(row){
x <- row[1]
y <- row[2]
if (is.na(x)|is.na(y)){
output<-NA
}
else if (x==2){
if (y==2){
output<-'previous_headache_maintained'
}else if(y==0){
output<-'previous_headache_ceased'
}
}else if(x %in% c(0,774,775,776)){
if (y==2){
output<-'new_onset_headache'
}else if (y %in% c(0, 774, 775, 776)){
output<-'no_headache'
}
}
}
You can then use simple apply
like this:
apply(df_headache_tibble, MARGIN = 1, incidence_headaches)
To get something like this:
> apply(df_headache_tibble, MARGIN = 1, incidence_headaches)
[1] "no_headache" "previous_headache_ceased" "previous_headache_maintained"
[4] "previous_headache_maintained" "new_onset_headache" "no_headache"
[7] "no_headache" "no_headache" "previous_headache_ceased"
[10] "new_onset_headache" "previous_headache_ceased" "previous_headache_maintained"
[13] "no_headache" "previous_headache_ceased" "no_headache"
...
2) mapply
is obviously a perfectly working function and there is no reason not to use it. Your problem was: tibbles are data.frames but they do not behave like data.frames. This works well:
mapply(incidence_headaches,
as.data.frame(df_headache_tibble)[,1],
as.data.frame(df_headache_tibble)[,2])
When you subset only one row from a data.frame, it will give you a vector, when you subset only one row from a tibble, it will give you a tibble. Hadley has a different opinion on how things should work then the people who invented the R data.frame. There are ways around this as in
mapply(incidence_headaches,
df_headache_tibble[,1, drop = TRUE],
df_headache_tibble[,2, drop = TRUE])
Read details here but mostly be always aware, that although tibbles are data.frames they do not behave exactly like data.frames: https://tibble.tidyverse.org/reference/subsetting.html
Related Topics
Extract Date from Given String in R
How to Plot a List of Vectors with Different Lengths
Convert a Mm-Yy String "Jan-01" into Date Format
How to Use With/Within Inside a Function
How to Suppress Warnings from Stats:::Regularize.Values
Loop Through a Series of Qplots
R: Interpolation of Nas by Group
How to Increase Smoothness of Spheres3D in Rgl
Print Tibble with Column Breaks as in V1.3.0
Vary the Color Gradient on a Scatter Plot Created with Ggplot2
Download Plotly Using Downloadhandler
Plot Line and Bar Graph (With Secondary Axis for Line Graph) Using Ggplot
Missing Data When Supplying a Dual-Axis--Multiple-Traces to Subplot
How to See All Rows of a Data Frame in a Jupyter Notebook with an R Kernel
Removing Particular Character in a Column in R
Can Sparklyr Be Used with Spark Deployed on Yarn-Managed Hadoop Cluster