Advice on how to use a for loop to compare columns and input into a vector

Viewed 65

I want to make a vector of counts comparing a number of columns to one called truth. I'm really not sure how this works, so any advice would be helpful because this isn't working for me so far.

k=13
for(i in 1:k){
  TPR<- tumor %>% filter(tumor1[,i]==T) %>% filter(tumor1[,i]==truth) %>% tally() 
}

For the sake of reproducibility, you can use this code, but it's really embarassing so there's that:

library(ggplot2)
library(dplyr)
library(tidyverse)

malig<-c(.49, .36, .58, .56, .61, .66)
benign<-c(.42, .22, .26, .53, .31 ,.41)

tumor<- NULL
tumor$malig<- malig
tumor$benign<- benign
tumor<-tumor %>% as.data.frame()

tumor<- tumor %>% pivot_longer(cols=c(malig,benign), names_to="status") %>% arrange(status)

cutoffs<-c(.2, .25, .3, .35, .37, .4, .45, .5, .55, .57, .6, .65, .7)

tumor<- tumor %>% mutate(tumor, Twenty = ifelse(value > .2, T, F))
tumor<- tumor %>% mutate(tumor, Twentyfive = ifelse(value > .25, T, F))
tumor<- tumor %>% mutate(tumor, Thirty = ifelse(value > .3, T, F))
tumor<- tumor %>% mutate(tumor, Thirtyfive = ifelse(value > .35, T, F))
tumor<- tumor %>% mutate(tumor, Thirtyseven = ifelse(value > .37, T, F))
tumor<- tumor %>% mutate(tumor, Forty = ifelse(value > .4, T, F))
tumor<- tumor %>% mutate(tumor, Fortyfive = ifelse(value > .45, T, F))
tumor<- tumor %>% mutate(tumor, Fifty = ifelse(value > .5, T, F))
tumor<- tumor %>% mutate(tumor, Fiftyfive = ifelse(value > .55, T, F))
tumor<- tumor %>% mutate(tumor, Fiftyseven = ifelse(value > .57, T, F))
tumor<- tumor %>% mutate(tumor, Sixty = ifelse(value > .6, T, F))
tumor<- tumor %>% mutate(tumor, Sixtyfive = ifelse(value > .65, T, F))
tumor<- tumor %>% mutate(tumor, Seventy = ifelse(value > .7, T, F))

tumor1<- tumor %>% mutate(tumor, truth=ifelse(status=="malig", T, F))
tumor1<- tumor1 %>% select(-value,-status)
k=13
for(i in 1:k){
  TPR<- tumor1 %>% filter(tumor1[,i]==T) %>% filter(tumor1[,i]==truth) %>% tally()
  
}
2 Answers

Maybe you are looking for something like this :

library(dplyr)

tumor1 %>% summarise(across(Twenty:Seventy, ~sum(. & truth)))

which in base R would be :

colSums(tumor1[-ncol(tumor1)] & tumor1$truth)

Here's a approach:

library(data.table)

lu_cutoffs = data.table(cutoffs = c(.2, .25, .3, .35, .37, .4, .45, .5, .55, .57, .6, .65, .7))

dt = setDT(stack(list(malig = malig,benign = benign)))
dt[, ind := as.character(ind)]

dt[ind == 'malig'
   ][lu_cutoffs,
   on = .(values > cutoffs),
   .N,
   by = .EACHI]

#    values     N
#     <num> <int>
# 1:   0.20     6
# 2:   0.25     6
# 3:   0.30     6
# 4:   0.35     6
# 5:   0.37     5
# 6:   0.40     5
# 7:   0.45     5
# 8:   0.50     4
# 9:   0.55     4
#10:   0.57     3
#11:   0.60     2
#12:   0.65     1
#13:   0.70     0

Basically, we first simplify the tidyr::pivot_longer with the stack line. Then, we filter to malig only and then do a non-equi join to a lookup of cutoffs.

This is a largely equivalent dplyr approach, although it looses the value 0.70.

tib = as_tibble(stack(list(malig = malig,benign = benign)))

tib %>%
  crossing(cutoffs)%>%
  filter(values > cutoffs,
         ind == "malig")%>%
  count(cutoffs) 

# # A tibble: 12 x 2
#    cutoffs     n
#      <dbl> <int>
#  1   0.2       6
#  2   0.25      6
#  3   0.3       6
#  4   0.35      6
#  5   0.37      5
#  6   0.4       5
#  7   0.45      5
#  8   0.5       4
#  9   0.55      4
# 10   0.570     3
# 11   0.6       2
# 12   0.65      1
Related