【问题标题】:How do I avoid loops in R?如何避免 R 中的循环?
【发布时间】:2021-08-10 16:57:03
【问题描述】:

我知道在R 中最好尽可能避免循环。在这方面,我想执行下面代码的功能,但不使用嵌套循环。

循环检查向量things_I_want_to_find 的第f' 元素是否存在于thing_to_be_searched 的第i' 行中。例如,当if 均为1 时,代码检查"vocals" 是否存在于john 的行中。因为"vocals" 出现在john 的行中,所以名称和仪器被添加到向量instrumentname。当两个循环都完成后,这两个向量可以组合成一个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

【问题讨论】:

    标签: r loops apply


    【解决方案1】:
    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】:

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

      【讨论】:

      【解决方案3】:

      base Rreshape 一起使用(与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
      

      【讨论】:

      • 在基础 R 中很好地使用管道!
      • base R 的惊人新功能。刚刚知道 R 4.1.0 已发布(由您的回答通知):P
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-03-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多