简体   繁体   中英

How do I avoid loops in R?

I understand that in R it is best to avoid loops where possible. In that regard, I would like to perform the function of the code below but without using the nested loops.

The loops check whether the f 'th element of the vector things_I_want_to_find is present in the i 'th row of thing_to_be_searched . For example, when both i and f are 1, the code checks whether "vocals" is present in john 's row. Because "vocals" is present in john 's row, the name and instrument are added to vectors instrument and name . When both loops are complete these two vectors can be combined in a data.frame .

I know that there is the apply() family of functions in R but I don't know if they are able to be used in this case. Has anyone got any helpful hints or suggestions?

instrument<-c()

name<-c()

things_I_want_to_find<-c("vocals","drums","rhythm guitar","bass")

thing_to_be_searched<-
data.frame(
id=c("john","paul","george","ringo"),
a=c("vocals","bass","rhythm guitar","oboe"),
b=c("vocals","basoon","piano","clarinet"),
c=c("violin","vocals","french horn","drums"))
for(f in 1:length(things_I_want_to_find))
{
  for(i in 1:nrow(thing_to_be_searched))
  {
    n<-which(thing_to_be_searched[i,]==things_I_want_to_find[f])
    if(length(n)>0)
    {
      instrument<-c(instrument,as.character(thing_to_be_searched[i,][n][,1][1]))
      name<-c(name,as.character(thing_to_be_searched$id[i]))
    }

    
  }
}

desired_output<-data.frame(name=name,instrument=instrument)
desired_output
    name    instrument
1   john        vocals
2   paul        vocals
3  ringo         drums
4 george rhythm guitar
5   paul          bass
library(tidyverse)
thing_to_be_searched %>%
  # Melt wide data to long
  pivot_longer(-1) %>%
  # Drop unwanted column
  select(-name) %>%
  # Filter wanted values only
  filter( value %in% things_I_want_to_find) %>%
  # Only keep unique rows
  unique()

output

# A tibble: 5 x 2
  id     value        
  <chr>  <chr>        
1 john   vocals       
2 paul   bass         
3 paul   vocals       
4 george rhythm guitar
5 ringo  drums 

Using base R with reshape (with R 4.1.0 )

thing_to_be_searched |>
   setNames(c('id', paste0('a', 1:3))) |>
   reshape(direction = 'long',  varying  = 2:4, sep="") |>
   subset(a %in% things_I_want_to_find, select = c(id, a)) |>
   unique() |>
   `row.names<-`(NULL)
#      id             a
#1   john        vocals
#2   paul          bass
#3 george rhythm guitar
#4   paul        vocals
#5  ringo         drums

Using dplyr -

library(dplyr)

thing_to_be_searched %>%
  group_by(id) %>%
  summarise(instrument = things_I_want_to_find[things_I_want_to_find %in% cur_data()]) %>%
  ungroup

#   id     instrument   
#  <chr>  <chr>        
#1 george rhythm guitar
#2 john   vocals       
#3 paul   vocals       
#4 paul   bass         
#5 ringo  drums        

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM