Eric González
Eric González

Reputation: 485

fill a table in a for loop with if statements in R

I would like to create a table depending on if elements in another table have certain values or characters in R.

Let´s say that I have this table:

test <- data.frame(col1=c(1,2,3,4,5), col2=c("AA","CC","GG","TT", "GG"))

I would like to create a table filing a row with certain values if the character in col2 is AA, other values if is CC, and so on.

I am trying the next script

test2<-c()
for(i in 1:nrow(test)) {
 if(test$col2[i]=="AA"){
  test2 <- rbind(test2, data.frame(0.91, 0.03, 0.03, 0.03))
 } else if (test$col2[i]=="CC"){
  test2 <- rbind(test2, data.frame(0.03, 0.91, 0.03, 0.03))
 } else if (geno_no_miss$V5[i] == "GG"){
  test2 <- rbind(test2, data.frame(0.03, 0.03, 0.91, 0.03))
 } else {
 test2 <- rbind(test2, data.frame(0.03, 0.03, 0.03, 0.91))
 }
}

This is producing the next optput:

   X0.91 X0.03 X0.03.1 X0.03.2
1  0.91  0.03    0.03    0.03
2  0.91  0.03    0.03    0.03
3  0.91  0.03    0.03    0.03
4  0.91  0.03    0.03    0.03
5  0.91  0.03    0.03    0.03

My desired output in this example is:

    V1    V2      V3      V4
1  0.91  0.03    0.03    0.03
2  0.03  0.91    0.03    0.03
3  0.03  0.03    0.91    0.03
4  0.03  0.03    0.03    0.91
5  0.03  0.03    0.91    0.03

Having the 0.91 in a different position depending on if in my table I have AA or CC or GG or TT. Could you please tell me how I could achieve this?

Upvotes: 0

Views: 844

Answers (2)

Onyambu
Onyambu

Reputation: 79228

First create a dataframe that has the results you need

results <- data.frame(key = c('AA', 'CC', 'GG', 'other'), 
                      V1 = c(0.91,0.03, 0.03,0.03),
                      V2 = c(0.03, 0.91,0.03,0.03),
                      V3 =  c(0.03,0.03, 0.91, 0.03),
                      V4 = c(0.03,0.03, 0.03, 0.91))

Then do a join/merge:

library(tidyverse)
test %>%
  mutate(key = ifelse(col2%in%res$key, col2, 'other'))%>%
  left_join(res, 'key')%>%
  select(-key)

col1 col2   V1   V2   V3   V4
1    1   AA 0.91 0.03 0.03 0.03
2    2   CC 0.03 0.91 0.03 0.03
3    3   GG 0.03 0.03 0.91 0.03
4    4   TT 0.03 0.03 0.03 0.91
5    5   GG 0.03 0.03 0.91 0.03

Upvotes: 0

Ronak Shah
Ronak Shah

Reputation: 388982

I would do it a bit differently. Growing objects/dataframe in a for loop is inefficient, use lists instead. Replace for loop with lapply since lapply naturally returns output as a list.

Write a function which returns a dataframe based on your condition.

return_data <- function(x) {
  if(x == 'AA') {
    data.frame(V1 = 0.91, V2 = 0.03,V3 =  0.03, V4 = 0.03)
  } else if(x == 'CC') {
    data.frame(V1 = 0.03, V2 = 0.91,V3 =  0.03, V4 = 0.03)
  } else if(x == 'GG') {
    data.frame(V1 = 0.03, V2 = 0.03,V3 =  0.91, V4 = 0.03)
  } else  {
    data.frame(V1 = 0.03, V2 = 0.03,V3 =  0.03, V4 = 0.91)
  }
}

do.call(rbind, lapply(test$col2, return_data))

#    V1   V2   V3   V4
#1 0.91 0.03 0.03 0.03
#2 0.03 0.91 0.03 0.03
#3 0.03 0.03 0.91 0.03
#4 0.03 0.03 0.03 0.91
#5 0.03 0.03 0.91 0.03

You can also use purrr::map_df(test$col2, return_data) which will return the same output.

Upvotes: 3

Related Questions