Hi guys,
I'd like to create a new column of a dataframe using for and if/else functions. My dataframe ds1 has the following 4 columns:
Sample_Name Sample_Well Sentrix_ID Sentrix_Position
pool_women A01 2,04426E+11 R01C01
213141 B01 2,04426E+11 R02C0
pool_men C01 2,04426E+11 R03C0
253141 D01 2,04426E+11 R04C01
202196 E01 2,04426E+11 R05C01
200569 F01 2,04426E+11 R06C01
242196 G01 2,04426E+11 R07C01
Now, I want to create a new column Sample_group, in which I should find 0 for samples starting with "21" and "20" in Sample_Name, 1 for samples starting with "25" and "24" in Sample_Names and 2 for the others (pool_women and pool_men), as following:
Sample_Name Sample_Well Sentrix_ID Sentrix_Position Sample_group
pool_women A01 2,04426E+11 R01C01 2
213141 B01 2,04426E+11 R02C01 0
pool_men C01 2,04426E+11 R03C01 2
253141 D01 2,04426E+11 R04C01 1
202196 E01 2,04426E+11 R05C01 0
200569 F01 2,04426E+11 R06C01 0
242196 G01 2,04426E+11 R07C01 1
I wrote the following code:
variables <- colnames(ds1[,which(colnames(ds1)=="Sample_Name")])
for(i in variables) {
if(gsub("(^\\d{2}).*", "\\1", i) == "21" | gsub("(^\\d{2}).*", "\\1", i) == "20") {ds1$Sample_group1 <- 0}
if(gsub("(^\\d{2}).*", "\\1", i) == "24" | gsub("(^\\d{2}).*", "\\1", i) == "25") {ds1$Sample_group1 <- 1}
else {ds1$Sample_group1 <- 2}
}
However, I found only 1 at the Sample_group column for all samples.
What's wrong with my code?
Thank you!
1 answer
Don't use for loops, that will access every single row, which will take ages if you have large data.frames.
#/ Example data:
df <- data.frame(Sample_Name=c("200", "211",
"240", "251",
"345", "456"))
#----------------------------------------------------------
# BASE R:
#----------------------------------------------------------
#/ new column with "2" (so other):
df$Sample_Group <- rep("2", nrow(df))
#/ and now replace 20/21s with 0 and 24/25s with 1:
df$Sample_Group[grep("^20|^21", df$Sample_Name)] <- 0
df$Sample_Group[grep("^24|^25", df$Sample_Name)] <- 1
> df
Sample_Name Sample_Group
1 200 0
2 211 0
3 240 1
4 251 1
5 345 2
6 456 2
#----------------------------------------------------------
# TIDYVERSE
#----------------------------------------------------------
library(tidyverse)
df %>%
mutate(Sample_Group =
case_when(str_detect(Sample_Name, "^20|^21") ~ "0",
str_detect(Sample_Name, "^24|^25") ~ "1",
!str_detect(Sample_Name, "^20|^21|^24|^25") ~ "2")
)
Sample_Name Sample_Group
1 200 0
2 211 0
3 240 1
4 251 1
5 345 2
6 456 2
The ^ means "starts with". The first solution is with only base R functions, the second one uses the tidyverse packages.
Next time please provide example data, e.g. via dput. If you have a data.frame named df you can run dput(df) and it will print an ASCII representation of the data which you can provide. That makes it easy to copy/paste your data rather than typing down things. Also try to provide a small but representative selection of the data or dummy data to keep the post short and readable.
Log in to answer this question.
input:
output:
with dplyr: