【问题标题】:How can I group by in R as in SQL?如何像在 SQL 中一样在 R 中分组?
【发布时间】:2018-11-23 12:07:11
【问题描述】:

我有这张桌子test

test<-matrix(c(1,1,1,1,1,2,2,2,2,2,2011,2012,2012,2013,2014,2011,2013,2013,2014,2014,1,1,3,2,1,2,1,1,3,1),  10,3)
test<-as_data_frame(test)
colnames(test)<-c("T","Y","S")

我想创建一个变量x,它是变量S 的总和,其中年份Y 与该行或一年前的行相同。

这正是我所期待的:

test<-cbind(test,c(1,5,5,6,3,2,4,4,6,6))
colnames(test)[4]<-"x"

我认为在 SQL 中是这样的(至少我记得):

proc sql;
create table test as select
a.T,
a.Y,
sum(case when Y eq a.Y or Y eq a.Y+1 then S else 0 end) as x
from test as a
group by T, Y;
end;

【问题讨论】:

    标签: r group-by aggregate


    【解决方案1】:

    尝试以下左自连接:

    library(sqldf)
    
    sqldf("select a.*, sum(b.S) as x 
      from test a 
      left join test b on a.T = b.T and b.Y between a.Y-1 and a.Y
      group by a.rowid")
    

    给予:

       T    Y S x
    1  1 2011 1 1
    2  1 2012 1 5
    3  1 2012 3 5
    4  1 2013 2 6
    5  1 2014 1 3
    6  2 2011 2 2
    7  2 2013 1 2
    8  2 2013 1 2
    9  2 2014 3 6
    10 2 2014 1 6
    

    注意

    这被用作产生上述输出的输入:

    test <- structure(list(T = c(1, 1, 1, 1, 1, 2, 2, 2, 2, 2), Y = c(2011, 
    2012, 2012, 2013, 2014, 2011, 2013, 2013, 2014, 2014), S = c(1, 
    1, 3, 2, 1, 2, 1, 1, 3, 1)), row.names = c(NA, -10L), class = "data.frame")
    

    【讨论】:

    • 完美!不仅是我期待的结果,而且是我正在寻找的方式(SQL)。另外,更正结果(我的错,你给出了正确的答案)。谢谢
    【解决方案2】:

    使用dplyr::left_join 的一个选项可以使用self-join 来实现。这个概念是将testtest 连接起来(在将Y 增加1 之后)。现在,如果您使用left_join 加入,则每一行将与属于Y 少1 个值的行加入。最后,必须sum 两个(S.x, S.y) 列(按行)。

    library(tidyverse)
    
    test %>% left_join(mutate(., Y = Y+1), by=c("T", "Y")) %>% 
      rowwise() %>%
      mutate(x = sum(S.x, S.y, na.rm = TRUE)) %>%
      select(T, Y, S = S.x, x) %>%
      as.data.frame()
    #    T    Y S x
    # 1  1 2011 1 1
    # 2  1 2012 1 2
    # 3  1 2012 3 4
    # 4  1 2013 2 3
    # 5  1 2013 2 5
    # 6  1 2014 1 3
    # 7  2 2011 2 2
    # 8  2 2013 1 1
    # 9  2 2013 1 1
    # 10 2 2014 3 4
    # 11 2 2014 3 4
    # 12 2 2014 1 2
    # 13 2 2014 1 2  
    

    【讨论】:

      【解决方案3】:

      我没有完全理解您要计算的内容,但您可以尝试使用 data.tables。语法为data.table[WHERE, SELECT, GROUP_BY],如果您习惯于 SQL,则很熟悉。应该是这样的:

      library(data.table)
      
      test.dt <- as.data.table(test)
      
      test.dt[ Y >= Y-1, x := sum(S), by = .(T, Y) ]
      

      := 表示创建一个名为“x”的新列(没有它只会显示结果)。

      【讨论】:

        【解决方案4】:

        如果我理解正确,您可以使用tidyverse 方法。

        require(tidyverse)
        
        test %>% 
          group_by(Y) %>% 
          mutate(x = sum(S, na.rm = TRUE)) %>% 
          ungroup()
        
               T     Y     S     x
           <dbl> <dbl> <dbl> <dbl>
         1    1. 2011.    1.    3.
         2    1. 2012.    1.    4.
         3    1. 2012.    3.    4.
         4    1. 2013.    2.    4.
         5    1. 2014.    1.    5.
         6    2. 2011.    2.    3.
         7    2. 2013.    1.    4.
         8    2. 2013.    1.    4.
         9    2. 2014.    3.    5.
        10    2. 2014.    1.    5.
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-12-20
          • 2023-04-01
          • 1970-01-01
          • 2020-04-08
          • 2016-07-10
          • 1970-01-01
          • 1970-01-01
          • 2016-04-24
          相关资源
          最近更新 更多