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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With