如何在R语言中避免循环?

4
我知道在R中尽量避免使用循环。因此,我想执行下面代码的功能但不使用嵌套循环。
这些循环检查向量things_I_want_to_find的第f个元素是否存在于thing_to_be_searched的第i行中。例如,当i和f都为1时,代码将检查“声乐”是否存在于john的行中。因为"vocals"确实存在于john的行中,所以将乐器和姓名添加到矢量instrument和name中。当两个循环完成后,这两个向量可以合并成一个data.frame。
我知道在R中有apply()函数家族,但我不知道它们能否用于此情况。有没有人有任何有用的提示或建议?
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
3个回答

4
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()

输出

# 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 

2

使用 R 4.1.0reshape 函数与 base R

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

1
基于R语言的管道使用得非常好! - Parfait
1
基础R的惊人新功能。刚刚得知R 4.1.0已发布(通过您的回答通知):P - ThomasIsCoding

2

使用 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        

1
今天我学到了:cur_data - zx8754

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接