将查询分组到组和子组中

时间:2014-09-08 09:08:54

标签: sql r sqlite greatest-n-per-group

我想使用SQL或R对数据进行分组,以便为​​每个Subarea_codesCompany获取最高或最低10 Area_code。实质上:Subarea_codes中的Area_codes,其中每个Company都有最大或最小的结果。

data.csv

Area_code  Subarea_code  Company   Result
10         101           A         15
10         101           P         10
10         101           C         4
10         102           A         10
10         102           P         8
10         102           C         5
11         111           A         15
11         111           P         20
11         111           C         5
11         112           A         10
11         112           P         5
11         112           C         10


result.csv should be like this

Company   Area_code  Largest_subarea_code  Result  Smallest_subarea_code    Result
A         10         101                   15      102                      10
P         10         101                   10      102                      8            
C         10         102                   5       101                      4
A         11         111                   15      112                      10
P         11         111                   20      112                      5
C         11         112                   10      111                      5

在每个Area_code内,可能有数百个Subarea_codes,但我只想要每个公司的最高和最低10个。

这也不必在一个查询中解析,但可以分为两个查询,意味着最小值显示在results_10_smallest中,最大值显示在result_10_largest中。但是我希望我能用一个查询来完成每个结果。

我尝试过的事情:

SELECT Company, Area_code, Subarea_code MAX(Result) 
    AS Max_result
FROM data
GROUP BY Subarea_code
ORDER BY Company
;

这为我提供了每个Subarea_code中具有最高结果的Companies。这意味着:A,A,P,A-C为上述数据。

5 个答案:

答案 0 :(得分:6)

使用sqldf包:

df <- read.table(text="Area_code  Subarea_code  Company   Result
10         101           A         15
10         101           P         10
10         101           C         4
10         102           A         10
10         102           P         8
10         102           C         5
11         111           A         15
11         111           P         20
11         111           C         5
11         112           A         10
11         112           P         5
11         112           C         10", header=TRUE)

library(sqldf)
mymax <- sqldf("select Company,
                  Area_code,
                  max(Subarea_code) Largest_subarea_code
                  from df
                  group by Company,Area_code")
mymaxres <- sqldf("select d.Company,
                          d.Area_code,
                          m.Largest_subarea_code,
                          d.Result
                  from df d, mymax m
                  where d.Company=m.Company and
                        d.Subarea_code=m.Largest_subarea_code")

mymin <- sqldf("select Company,
                  Area_code,
                  min(Subarea_code) Smallest_subarea_code
                  from df
                  group by Company,Area_code")
myminres <- sqldf("select d.Company,
                          d.Area_code,
                          m.Smallest_subarea_code,
                          d.Result
                  from df d, mymin m
                  where d.Company=m.Company and
                        d.Subarea_code=m.Smallest_subarea_code")
result <- sqldf("select a.*, b.Smallest_subarea_code,b.Result
                from mymaxres a, myminres b
                where a.Company=b.Company and 
                      a.Area_code=b.Area_code")

答案 1 :(得分:5)

如果您已在R中执行此操作,为什么不使用SQL语法来使用效率更高的data.table而不是sqldf?假设data是您的数据集,只需:

library(data.table)
setDT(data)[, list(Largest_subarea_code = Subarea_code[which.max(Result)],
            Resultmax = max(Result),
            Smallest_subarea_code = Subarea_code[which.min(Result)],
            Resultmin = min(Result)), by = list(Company, Area_code)]
#    Company Area_code Largest_subarea_code Resultmax Smallest_subarea_code Resultmin
# 1:       A        10                  101        15                   102        10
# 2:       P        10                  101        10                   102         8
# 3:       C        10                  102         5                   101         4
# 4:       A        11                  111        15                   112        10
# 5:       P        11                  111        20                   112         5
# 6:       C        11                  112        10                   111         5

答案 2 :(得分:1)

显示的输出与描述之间似乎存在差异。描述要求每个区号/公司的前10名和后10名结果,但样本输出仅显示前1和后1。例如,对于区号10和公司A子区域101是顶部,结果为15并且子区域102是第二大的,结果为10,因此根据描述,该公司/区域代码组合应该有两行。 (如果有更多数据,那么该公司/区号组合最多可以有10行。)

我们给出两个答案。第一个假设每个公司和区域代码需要前10个和后10个,如问题的描述,第二个假设每个公司和区域代码的顶部和底部,如问题的样本输出

1)上/下10

这里我们假设需要每个公司/区域代码的前10个和后10个结果。如果它只是顶部和底部,那么稍后会看到(2)(或者在代码中用10代替10)。 Bottom10是相同区域代码的10个或更少子区域以及具有相同或更小结果的公司的所有行。 Top10类似。

library(sqldf)

Bottom10 <- sqldf("select a.Company, 
                          a.Area_code, 
                          a.Subarea_code Bottom_Subarea, 
                          a.Result Bottom_Result,
                          count(*) Bottom_Rank
        from df a join df b  
        on a.Company = b.Company and 
           a.Area_code = B.Area_code and
           b.Result <= a.Result
        group by a.Company, a.Area_code, a.Subarea_code
        having count(*) <= 10")

Top10 <- sqldf("select a.Company, 
                       a.Area_code, 
                       a.Subarea_code Top_Subarea, 
                       a.Result Top_Result,
                       count(*) Top_Rank
        from df a join df b  
        on a.Company = b.Company and 
           a.Area_code = B.Area_code and 
           b.Result >= a.Result
        group by a.Company, a.Area_code, a.Subarea_code
        having count(*) <= 10")

说明表明您希望每个公司/地区代码的前10名或后10名,在这种情况下只需使用上述结果之一。如果你想组合它们,我们在下面显示合并。我们添加了一个Rank列来表示最小/最大(Rank为1),第二个最小/最大(Rank为2)等。

sqldf("select t.Area_code, 
              t.Company, 
              t.Top_Rank Rank,
              t.Top_Subarea, 
              t.Top_Result,
              b.Bottom_Subarea,
              b.Bottom_Result
       from Bottom10 b join Top10 t
       on t.Area_code = b.Area_code and 
          t.Company = b.Company and
          t.Top_Rank = b.Bottom_Rank
       order by t.Area_code, t.Company, t.Top_Rank")

,并提供:

   Area_code Company Rank Top_Subarea Top_Result Bottom_Subarea Bottom_Result
1         10       A    1         101         15            102            10
2         10       A    2         102         10            101            15
3         10       C    1         102          5            101             4
4         10       C    2         101          4            102             5
5         10       P    1         101         10            102             8
6         10       P    2         102          8            101            10
7         11       A    1         111         15            112            10
8         11       A    2         112         10            111            15
9         11       C    1         112         10            111             5
10        11       C    2         111          5            112            10
11        11       P    1         111         20            112             5
12        11       P    2         112          5            111            20

请注意,如果存在关联,此格式不太合理,实际上,可能会为公司/区域代码生成10行以上,因此您可能只想使用个人Top10和{{1} } 在这种情况下。如果这是一个问题,你也可以考虑抖动Bottom10

df$Result

2)仅限上/下

这里我们只给出每个公司/地区代码的顶部和底部结果以及相应的子区域。请注意,这使用了sqlite支持的SQL扩展,并且SQL代码基本上更简单:

df$Result <- jitter(df$Result)
# now perform SQL statements

这给出了:

Bottom1 <- sqldf("select Company, 
                          Area_code, 
                          Subarea_code Bottom_Subarea, 
                          min(Result) Bottom_Result
        from df
        group by Company, Area_code")

Top1 <- sqldf("select Company, 
                      Area_code, 
                      Subarea_code Top_Subarea, 
                      max(Result) Top_Result
        from df
        group by Company, Area_code")

sqldf("select a.Company, 
              a.Area_code, 
              Top_Subarea, 
              Top_Result,
              Bottom_Subarea
              Bottom_Result
        from Top1 a join Bottom1 b  
        on a.Company = b.Company and 
           a.Area_code = b.Area_code
        order by a.Area_code, a.Company")

更新更正并添加(2)。

答案 3 :(得分:0)

以上答案可以获取最大结果。

这解决了前10个问题:

data.top <- data[ave(-data$Result, data$Company, data$Area_code, FUN = rank) <= 10, ]

答案 4 :(得分:0)

在此脚本中,用户声明公司。然后该脚本指示最大前10个结果(最小值的同意值)。

Result=NULL
A <- read.table(/your-file.txt",header=T,sep="\t",na.string="NA")
Company<-A$Company=="A" #can be A, C, P or other values

Subarea<-unique(A$Subarea)

for (i in 1:length(unique(A$Subarea)))
{Result[i]<-max(A$Result[Company & A$Subarea_code==Subarea[i]])}
Res1<-t((rbind(Subarea,Result)))
Res2<-Res1[order(-Res1[,2]),]
Res2[1:10,]