【问题标题】:Newbie working on Horse Racing Database using R新手使用 R 研究赛马数据库
【发布时间】:2020-05-24 09:35:12
【问题描述】:

我是小组和 R 语言的新手。 我已经编写了一些代码(如下)来达到预期的结果。 但是,我知道我正在复制相同代码的行,使用 for 循环肯定会更有效地编码。 此外,会有大量马匹的比赛,所以我真的需要能够运行一个贯穿每匹马的 for 循环。 IE。 num_runners = NROW(my_new_data)

my_new_data 保存有关马匹之前比赛的数据。 DaH 是一个数字等级,附加到每匹马以前的跑步,DaH1 是最近的,而 DaH6 是六场比赛。 代码,一个字符,表示马匹参加的比赛类型。即。平坦,栅栏。

我玩过使用 for 循环,即。 for(i in 1:6) 没有成功。 由于我每次都分配给一匹新马,因此我希望以下内容会起作用:

horse(i) = c(my_new_data$DaH1[i],my_new_data$DaH2[i],my_new_data$DaH3[i],my_new_data$DaH4[i],my_new_data$DaH5[i],my_new_data$DaH6[i])
But I know that horse(i) is not allowed.
Would my best strategy be to pre-define a dataframe of size: 6 rows and 6 columns

并使用 2 个 for 循环来填充 [row][column]?比如:

final_data[i,j] 

这是我目前使用的用于创建数据框racetest的代码:

horse1 = c(my_new_data$DaH1[1],my_new_data$DaH2[1],my_new_data$DaH3[1],my_new_data$DaH4[1],my_new_data$DaH5[1],my_new_data$DaH6[1])
horse2 = c(my_new_data$DaH1[2],my_new_data$DaH2[2],my_new_data$DaH3[2],my_new_data$DaH4[2],my_new_data$DaH5[2],my_new_data$DaH6[2])
horse3 = c(my_new_data$DaH1[3],my_new_data$DaH2[3],my_new_data$DaH3[3],my_new_data$DaH4[3],my_new_data$DaH5[3],my_new_data$DaH6[3])
horse4 = c(my_new_data$DaH1[4],my_new_data$DaH2[4],my_new_data$DaH3[4],my_new_data$DaH4[4],my_new_data$DaH5[4],my_new_data$DaH6[4])
horse5 = c(my_new_data$DaH1[5],my_new_data$DaH2[5],my_new_data$DaH3[5],my_new_data$DaH4[5],my_new_data$DaH5[5],my_new_data$DaH6[5])
horse6 = c(my_new_data$DaH1[6],my_new_data$DaH2[6],my_new_data$DaH3[6],my_new_data$DaH4[6],my_new_data$DaH5[6],my_new_data$DaH6[6])
horse1.code = c(my_new_data$Code1[1],my_new_data$Code2[1],my_new_data$Code3[1],my_new_data$Code4[1],my_new_data$Code5[1],my_new_data$Code6[1])
horse2.code = c(my_new_data$Code1[2],my_new_data$Code2[2],my_new_data$Code3[2],my_new_data$Code4[2],my_new_data$Code5[2],my_new_data$Code6[2])
horse3.code = c(my_new_data$Code1[3],my_new_data$Code2[3],my_new_data$Code3[3],my_new_data$Code4[3],my_new_data$Code5[3],my_new_data$Code6[3])
horse4.code = c(my_new_data$Code1[4],my_new_data$Code2[4],my_new_data$Code3[4],my_new_data$Code4[4],my_new_data$Code5[4],my_new_data$Code6[4])
horse5.code = c(my_new_data$Code1[5],my_new_data$Code2[5],my_new_data$Code3[5],my_new_data$Code4[5],my_new_data$Code5[5],my_new_data$Code6[5])
horse6.code = c(my_new_data$Code1[6],my_new_data$Code2[6],my_new_data$Code3[6],my_new_data$Code4[6],my_new_data$Code5[6],my_new_data$Code6[6])

racetest = data.frame(horse1,horse1.code,horse2,horse2.code, horse3, horse3.code,
                      horse4,horse4.code,horse5,horse5.code, horse6, horse6.code)

提前感谢您提供的任何帮助! 格雷厄姆

【问题讨论】:

    标签: r database for-loop


    【解决方案1】:

    在 R 中使用循环通常不是正确的方法。不过我会给你一些可能有用的东西。

    我在这里看到了两种可能的方法,我将介绍更简单的一种:

    如果对列进行排序,使得列 1:6 被命名为 DaH1DaH6 并且列 7:12 被命名为 horse1.code 等等......在这种情况下:

    library(magrittr)
    
    temp<- cbind(my_new_data[,1:6] %>% t,
                 my_new_data[,7:12]%>% t)
    
    Odd = seq(1,12,2)
    
    my_new_data[ , Odd] = temp[,1:6]
    my new_data[ , -Odd] = temp[,7:12]
    
    #cleanup
    rm(temp,Odd)
    

    my_new_data 现在应该包含您想要的输出。在运行之前,请确保您的数据已备份在另一个对象中,因为这是未经测试的代码。

    【讨论】:

      【解决方案2】:

      其实我们是想reshape把数据换成不同的宽格式。但首先让我们看看您想要的for 循环方法,以了解发生了什么。

      使用循环

      对于循环,我们需要两个具有序列ij 的变量。

      ## initialize matrix with dimnames
      racetest <- matrix(NA, 3, 6, 
                         dimnames=list(c("DaH1", "DaH2", "DaH3"), 
                                       c("horse1", "horse1.code", "horse2", "horse2.code", 
                                         "horse3", "horse3.code")))
      
      ## loop
      for (i in 0:2) {
        for (j in 1:3) {
          racetest[j, 1:2+2*i] <- unlist(my_new_data[i+1, c(1, 4)])
        }
      }
      #      horse1 horse1.code horse2 horse2.code horse3 horse3.code
      # DaH1      1           1      2           2      3           3
      # DaH2      1           1      2           2      3           3
      # DaH3      1           1      2           2      3           3
      

      在 R 中通常不鼓励使用 for 循环,因为它们可能很慢并且不使用 vectorized features of the R language。此外,它们的编程也很棘手。

      转置列集

      我们也可以采用不同的方法。实际上,我们想要transpose DaH*Code* 列集(可使用grep 识别)并使用namessubstring 将它们带入适当的order,其中nchar 作为第一个字符.

      rownames(my_new_data) <- paste0("horse.", seq(nrow(my_new_data)))
      rr <- data.frame(DaH=t(my_new_data[, grep("DaH", names(my_new_data))]), 
                       Code=t(my_new_data[, grep("Code", names(my_new_data))]))
      rr <- rr[order(substring(names(rr), nchar(names(rr))))]
      rr
      #      DaH.horse.1 Code.horse.1 DaH.horse.2 Code.horse.2 DaH.horse.3 Code.horse.3
      # DaH1           1            1           2            2           3            3
      # DaH2           1            1           2            2           3            3
      # DaH3           1            1           2            2           3            3
      

      重塑数据

      最后但同样重要的是,我们实际上想要reshape 数据。为此,我们给数据集一个 ID 变量。

      my_new_data <- transform(my_new_data, horse=1:nrow(my_new_data))
      

      首先,我们将reshape的数据转化为"long"的格式,使用新的ID变量horse,将两个varying列集合放到一个列表中。

      rr1 <- reshape(my_new_data, idvar="horse", varying=list(1:3, 4:6), direction="long", sep="",
                     v.names=c("DaH", "Code"))
      rr1
      #     horse time DaH Code
      # 1.1     1    1   1    1
      # 2.1     2    1   2    2
      # 3.1     3    1   3    3
      # 1.2     1    2   1    1
      # 2.2     2    2   2    2
      # 3.2     3    2   3    3
      # 1.3     1    3   1    1
      # 2.3     2    3   2    2
      # 3.3     3    3   3    3
      

      然后,为了获得所需的宽格式,我们想要交换idvartimevar,其中我们的新idvar"time",我们新的timevar"horse"

      reshape(rr1, timevar="horse", idvar="time", direction= "wide")
      #     time DaH.1 Code.1 DaH.2 Code.2 DaH.3 Code.3
      # 1.1    1     1      1     2      2     3      3
      # 1.2    2     1      1     2      2     3      3
      # 1.3    3     1      1     2      2     3      3
      

      基准测试

      基准测试表明,在这三种方法中,transposing 矩阵最快,而“for”循环实际上是迄今为止最慢的。

      # Unit: microseconds
      #       expr      min        lq      mean   median        uq       max neval cld
      #    forloop 7191.038 7373.5890 8381.8036 7576.678 7980.4320 46677.324   100   c
      #  transpose  620.748  656.0845  707.7248  692.953  733.1365   944.773   100 a  
      #    reshape 2791.710 2858.6830 3013.8372 2958.825 3118.4125  3871.960   100  b 
      

      玩具数据:

      my_new_data <- data.frame(DaH1=1:3, DaH2=1:3, DaH3=1:3, Code1=1:3, Code2=1:3, Code3=1:3)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-04-27
        • 2019-07-12
        • 2012-07-13
        • 1970-01-01
        • 2011-04-26
        • 1970-01-01
        相关资源
        最近更新 更多