【问题标题】:find first occurrence in two variables in df在 df 的两个变量中找到第一次出现
【发布时间】:2019-11-24 03:11:18
【问题描述】:

我需要找到我的 df 满足由两个变量分组的特定条件的前两次。我正在尝试使用 ddply 函数,但“.variables”命令出现问题。

所以在这个例子中,我试图在每个组/试验中找到前两次 x > 30 和 y > 30。

我使用 ddply 的方式是在数据集中给我前两次,然后对每个组重复。

 set.seed(1)
 df <- data.frame((matrix(nrow=200,ncol=5)))
 colnames(df) <- c("group","trial","x","y","hour")
 df$group <- rep(c("A","B","C","D"),each=50)
 df$trial <- rep(c(rep(1,times=25),rep(2,times=25)),times=4)
 df[,3:4] <- runif(400,0,50)
 df$hour <- rep(1:25,time=8)


 library(plyr)
 ddply(.data=df, .variables=c("group","trial"), .fun=function(x) {
   i <- which(df$x > 30 & df$y >30 )[1:2]
   if (!is.na(i)) x[i, ] 
 })

预期结果:

    group trial           x          y hour
 13      A     1 34.3511423 38.161134   13
 15      A     1 38.4920710 40.931734   15
 36      A     2 33.4233369 34.481392   11
 37      A     2 39.7119930 34.470671   12
 52      B     1 43.0604738 46.645491    2
 65      B     1 32.5435234 35.123126   15

但相反,我的代码是从第一组试验中找到 c(1,4)并为每个试验组重复一遍:

   group trial         x         y hour
 1      A     1 34.351142 38.161134   13
 2      A     1 38.492071 40.931734   15
 3      A     2  5.397181 27.745031   13
 4      A     2 20.563721 22.636003   15
 5      B     1 22.953286 13.898301   13
 6      B     1 32.543523 35.123126   15

如果组*试验中没有第二次出现,我还希望有 NA 行。

谢谢,

【问题讨论】:

  • 您的预期输出似乎与您的输入数据不匹配。请仔细检查。
  • 抱歉,设置为不同的种子。感谢您指出。现已更正。

标签: r vector subset plyr


【解决方案1】:

我想这就是你想要的:

library(tidyverse)
df %>% group_by(group, trial) %>% filter(x > 30 & y > 30) %>% slice(1:2)

结果:

# A tibble: 16 x 5
# Groups:   group, trial [8]
   group trial     x     y  hour
   <chr> <dbl> <dbl> <dbl> <int>
 1 A         1  33.5  46.3     4
 2 A         1  32.6  42.7    11
 3 A         2  35.9  43.6     4
 4 A         2  30.5  42.7    14
 5 B         1  33.0  38.1     2
 6 B         1  40.5  30.4     7
 7 B         2  48.6  33.2     2
 8 B         2  34.1  30.9     4
 9 C         1  33.0  45.1     1
10 C         1  30.3  36.7    17
11 C         2  44.8  33.9     1
12 C         2  41.5  35.6     6
13 D         1  44.2  34.3    12
14 D         1  39.1  40.0    23
15 D         2  39.4  47.5     4
16 D         2  42.1  40.1    10

(与您的结果略有不同,可能是不同的 R 版本)

【讨论】:

    【解决方案2】:

    我建议使用dplyr 或data.table 而不是plyr。来自plyrgithub页面:

    plyr 已退役:这意味着只需进行必要的更改以将其保留在 CRAN 将被制作。我们建议使用 dplyr(用于数据帧)或 purrr(用于 列表)代替。

    由于有人已经通过dplyr 提供了解决方案,因此这里是 data.table 的一个选项。

    在选择 df[i, j, k] 中,我在i 中选择符合您的条件的行,按k 中的给定变量分组,并选择每个组特定子集的前两行 (head)数据.SD。括号内的所有这些都是特定于 data.table 的,并且仅因为我首先使用 setDT 将 df 转换为 data.table 才有效。

    library(data.table)
    setDT(df) 
    
    df[x > 30 & y > 30, head(.SD, 2), by = .(group, trial)]
    
    #     group trial        x        y hour
    #  1:     A     1 34.35114 38.16113   13
    #  2:     A     1 38.49207 40.93173   15
    #  3:     A     2 33.42334 34.48139   11
    #  4:     A     2 39.71199 34.47067   12
    #  5:     B     1 43.06047 46.64549    2
    #  6:     B     1 32.54352 35.12313   15
    #  7:     B     2 48.03090 38.53685    5
    #  8:     B     2 32.11441 49.07817   18
    #  9:     C     1 32.73620 33.68561    1
    # 10:     C     1 32.00505 31.23571   20
    # 11:     C     2 32.13977 40.60658    9
    # 12:     C     2 34.13940 49.47499   16
    # 13:     D     1 36.18630 34.94123   19
    # 14:     D     1 42.80658 46.42416   23
    # 15:     D     2 37.05393 43.24038    3
    # 16:     D     2 44.32255 32.80812    8
    

    【讨论】:

      【解决方案3】:

      要尝试更接近您迄今为止尝试过的解决方案,我们可以执行以下操作

      ddply(.data=df, .variables=c("group","trial"), .fun=function(df_temp) {
        i <- which(df_temp$x > 30 & df_temp$y >30 )[1:2]
        df_temp[i, ]
      })
      

      一些解释

      您提供的代码的一个问题是您在ddply 内部使用了df。因此,您定义了fun= function(x),但您没有在x 中查找x&gt; 30 &amp; y&gt; 30 的情况,而是在df 中查找。此外,您的代码将i 用于x,但i 是用df 定义的。最后,据我了解,不需要if (!is.na(i)) x[i, ]。如果只有一行符合您的条件,您将得到一行NAs 反正,因为您使用which(df_temp$x &gt; 30 &amp; df_temp$y &gt;30 )[1:2]。

      【讨论】:

        【解决方案4】:

        使用dplyr,你也可以这样做:

        df %>%
         group_by(group, trial) %>%
         slice(which(x > 30 & y > 30)[1:2])
        
           group trial     x     y  hour
           <chr> <dbl> <dbl> <dbl> <int>
         1 A         1  34.4  38.2    13
         2 A         1  38.5  40.9    15
         3 A         2  33.4  34.5    11
         4 A         2  39.7  34.5    12
         5 B         1  43.1  46.6     2
         6 B         1  32.5  35.1    15
         7 B         2  48.0  38.5     5
         8 B         2  32.1  49.1    18
        

        【讨论】:

          【解决方案5】:

          由于此处涵盖的所有其他内容都是使用 split 的基本 R 版本

          output <- do.call(rbind, lapply(split(df, list(df$group, df$trial)), 
              function(new_df) new_df[with(new_df, head(which(x > 30 & y > 30), 2)), ]
          ))
          rownames(output) <- NULL
          
          output
          #   group trial      x      y hour
          #1      A     1 34.351 38.161   13
          #2      A     1 38.492 40.932   15
          #3      B     1 43.060 46.645    2
          #4      B     1 32.544 35.123   15
          #5      C     1 32.736 33.686    1
          #6      C     1 32.005 31.236   20
          #7      D     1 36.186 34.941   19
          #8      D     1 42.807 46.424   23
          #9      A     2 33.423 34.481   11
          #10     A     2 39.712 34.471   12
          #11     B     2 48.031 38.537    5
          #12     B     2 32.114 49.078   18
          #13     C     2 32.140 40.607    9
          #14     C     2 34.139 49.475   16
          #15     D     2 37.054 43.240    3
          #16     D     2 44.323 32.808    8
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-04-26
            • 2019-10-15
            • 2017-05-06
            • 2011-05-23
            • 1970-01-01
            相关资源
            最近更新 更多