如何在R中像在SQL中一样分组?

如何在R中像在SQL中一样分组?,r,group-by,aggregate,R,Group By,Aggregate,我有这个表格测试 我认为在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; 如果我理解正确,您可以使用tidyverse方法 require(tidyverse) test %>% group_by(Y) %>

我有这个表格测试

我认为在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;

如果我理解正确,您可以使用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.

如果我理解正确,您可以使用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.

尝试以下左自联接:

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")

尝试以下左自联接:

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")
使用dplyr::left_连接的一个选项可以通过使用自连接实现。其概念是在Y增加1后将test与test连接起来。现在,如果使用left_join进行连接,那么每一行都将使用一个小于Y值1的行进行连接。最后,必须将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  
使用dplyr::left_连接的一个选项可以通过使用自连接实现。其概念是在Y增加1后将test与test连接起来。现在,如果使用left_join进行连接,那么每一行都将使用一个小于Y值1的行进行连接。最后,必须将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  

我并不完全理解您试图计算的内容,但您可以尝试使用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的新列,而不使用它,它将只显示结果。

我不完全理解您试图计算的内容,但您可以尝试使用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的新列,而不使用它,它将只显示结果。

Perfect!不仅是我期望的结果,而且是我寻找SQL的方式。另外,纠正结果我不好,你给出了正确的答案。太完美了!不仅是我期望的结果,而且是我寻找SQL的方式。另外,纠正结果我不好,你给出了正确的答案。Thks