1
votes

I am trying to use the dplyr package but I am facing a problem with handling variable.

Let say I have a simplify dataframe

my.data <- as.data.frame(matrix(NA), ncol=4, nrow=6)
my.data <- as.data.frame(cbind(c("d6", "d7", "d8", "d9", "da", "db"), c(rep("C200", 2), rep("C400", 4)), c(rep("a",5), "b"), c("c", rep("a", 5))))
colnames(my.data) <- c("snp", "gene", "ind1", "ind2")

I first count the number of snp per gene with the group_by:

new.data <- my.data %>% group_by(gene) %>% mutate(count = n())

But then I want to get the string occurence as percentage by gene for each individual column:

new.data %>% group_by(gene) %>% filter(grepl("a", ind1)) %>% dplyr::mutate(perc.a.ind1 = n()/count*100)
new.data %>% group_by(gene) %>% filter(grepl("a", ind2)) %>% dplyr::mutate(perc.a.ind2 = n()/count*100)

and it is working fine. The thing is that I have many individuals and I need to automatize it. So I create a vector of names and run my function within a for loop (I know loop is not best, I would be happy to upgrade to an apply version or something else)

ind.vec <- colnames(my.data[,3:4])
for (i in 1:length(ind.vec){
new.data %>% group_by(gene) %>% filter(grepl("a", ind.vec[i])) %>% mutate(percent = n()/count*100)

}

I ended up with an empty tibble, just like none element of my ind.vec is recognized.

I read the vignette https://cran.r-project.org/web/packages/dplyr/vignettes/programming.html, that lets me think I have identified the problem, but I am far from understanding it and unable to make it worked with my data.

I made some trial with

ind.vec <- quote(colnames(my.data[,3:4]))
new.data %>% group_by(gene) %>% filter(grepl("a", !!(ind.vec[i]))) %>% mutate(percent = n()/count*100)

How can I make the vector element recognized by dplyr ?

May you help please?

2
@IanWesley, thank you for mentionning that post. It's closed to my problem but in my case I have to handle ind.vec[i], and the index gives me trouble as it is not regonized in as.name(ind.vec).N.Goue

2 Answers

0
votes

I suggest you use tidyr::gather for this.

library(tidyverse)
# or library(dplyr);library(tidyr)

my.data %>% 
  group_by(gene) %>% 
  mutate(count = n()) %>% 
  gather(ind, string, ind1, ind2 ) %>% 
  filter(string == "a") %>% 
  group_by(gene, ind, string) %>% 
  mutate(
    n_string = n(),
    freq = n_string /  count * 100 ) 

# A tibble: 10 x 7
# Groups:   gene, ind, string [4]
#      snp   gene count   ind string n_string  freq
#    <fctr> <fctr> <int> <chr>  <chr>    <int> <dbl>
# 1     d6   C200     2  ind1      a        2   100
# 2     d7   C200     2  ind1      a        2   100
# 3     d8   C400     4  ind1      a        3    75
# 4     d9   C400     4  ind1      a        3    75
# 5     da   C400     4  ind1      a        3    75
# 6     d7   C200     2  ind2      a        1    50
# 7     d8   C400     4  ind2      a        4   100
# 8     d9   C400     4  ind2      a        4   100
# 9     da   C400     4  ind2      a        4   100
#10     db   C400     4  ind2      a        4   100

I get a warning for some reason, but the results are the same as the one's you provided.

0
votes

@SollanoRabeloBraga, thank you so much!! It solves my problem. I modified the gather function to include more individuals gather(ind, string, ind1:ind5) then I did

new.data <- test[!duplicated(new.data[, c("gene", "ind", "freq")]),]

new.data <- cast(test2, gene ~ ind)

to polish my results.