0

因此,我试图找到数据集的每个客户 ID 每年的最大、第二个最大和第三个最大用水量。我正在使用 R 和 sqldf 库,但我对任何 R 解决方案持开放态度。这是一些示例数据:

 Year  | ID | Month  | Use |
----------------------------
2009    101 1   103

2009    101 2   209

2009    101 3   375

2009    101 4   360

2010    101 1   170

2010    101 2   381

2010    101 3   275

2010    101 4   260

2009    102 1   263

2009    102 2   234

2009    102 3   45

2009    102 4   275

2010    102 1   469

2010    102 2   107

2010    102 3   354

2010    102 4   436

理想情况下,我想返回三个矩阵,,,,max1列,,,max2(或第二个最大值或第三个最大值,分别) 等等。max3IDYearMaxmax1 = [101, 2009, 375, 101, 2010, 381, 102, 2009, 275, 102, 2010, 469]

我最初的方法是使用listofIDsandlistofYears作为 and 的域ID创建一个嵌套的 for 循环Year,例如:

for i in 1:length(listofIDs){

for y in 1:length(listofYears){

monthlylist<-sqldf("select Month, Use from Dataframe where ID=listofIDs[i] and Year=listofYears[y]")

然后排序monthlylist并取出最大值等。但sqldf不会读取这样的变量,所以我必须每次明确说明 where ID = 101, where 。ID = 102

关于如何让 sqldf 识别我的变量的任何想法,或者找到按年份和 ID 聚合的最大值、第二个最大值和第三个最大值的更好方法?我正在处理大型数据集,因此理想情况下不会永远持续下去。

4

2 回答 2

2

以下代码创建三个数据框的列表(dat是您的原始数据框):

lapply(seq(3), function(x)
  aggregate(Use ~ Year + ID, dat, function(y)
    y[order(-y)][x]))

结果:

[[1]]
  Year  ID Use
1 2009 101 375
2 2010 101 381
3 2009 102 275
4 2010 102 469

[[2]]
  Year  ID Use
1 2009 101 360
2 2010 101 275
3 2009 102 263
4 2010 102 436

[[3]]
  Year  ID Use
1 2009 101 209
2 2010 101 260
3 2009 102 234
4 2010 102 354

它是如何工作的

该函数lapply用于多次应用另一个函数。该命令seq(3)生成一个从 1 到 3 的数字向量。参数x代表这些数字之一。该函数aggregate用于将另一个函数应用于由和Use分组的值。该参数表示一组中的值。该命令按降序对值进行排序。之后,分别用于提取该有序向量的第一个、第二个和第三个元素。YearIDyUsey[order(-y)]Use[x]

于 2013-11-19T22:01:00.257 回答
1

首先以易于重现的形式设置测试数据:

# set up test data

Lines <- "Year ID Month Use
2009 101 1 103
2009 101 2 209
2009 101 3 375
2009 101 4 360
2010 101 1 170
2010 101 2 381
2010 101 3 275
2010 101 4 260
2009 102 1 263
2009 102 2 234
2009 102 3 45
2009 102 4 275
2010 102 1 469
2010 102 2 107
2010 102 3 354
2010 102 4 436
"
DF <- read.table(text = Lines, header = TRUE)

现在我们有了输入数据,这里有一些方法:

1) sqldf/SQLite以下三个 SQL 语句应该计算这些数量。如果它们运行得太慢,您可以尝试添加年份,ID 索引。请注意,这三个 SQL 语句除了from子句之外是相同的:

现在创建三个数据框:

library(sqldf)

max1 <- sqldf("select Year, ID, max(Use) Use 
   from DF 
   group by Year, ID") 

max2 <- sqldf("select Year, ID, max(Use) Use 
   from (select Year, ID, Use from DF 
         except select * from max1) 
   group by Year, ID")

max3 <- sqldf("select Year, ID, max(Use) Use 
   from (select Year, ID, Use from DF 
         except select * from max1 
         except select * from max2) 
   group by Year, ID")

2) sqldf/PostgreSQL以上是针对带有 sqlite 的 sqldf 但使用 sqldf 和 PostgreSQL 更容易,因为那时我们可以使用 PostgreSQL 的rank()窗口函数。(这里有更多关于使用 PostgreSQL 和 sqldf 的信息。)

library(RPostgreSQL)
library(sqldf)

DF2 <- sqldf('select *, rank() over (partition by "Year", "ID" order by "Use" desc) 
              from "DF"')
split(DF2[1:4], DF2$rank)[1:3]

最后一行可以替换为:

lapply(1:3, function(r) subset(DF2, rank == r)[1:4])

如果我们想要一个纯 SQL 解决方案,那么:

max1 <- sqldf('select "Year", "ID", "Month", "Use" from "DF2" where "rank" = 1')
max2 <- sqldf('select "Year", "ID", "Month", "Use" from "DF2" where "rank" = 2')
max3 <- sqldf('select "Year", "ID", "Month", "Use" from "DF2" where "rank" = 3') 

或生成数据框列表:

lapply(1:3, function(r) 
   fn$sqldf('select "Year", "ID", "Month", "Use" from "DF2" where "rank" = $r'))

3) ave在直 R 中这样做并不难。这里 Rank 1 是最大的,Rank 2 是第二大的,依此类推,所以我们只是Rank像之前的解决方案一样拆分并取前三个组件:

Rank <- with(DF, ave(-Use, Year, ID, FUN = rank))
split(DF, Rank)[1:3]

这也可以代替最后一行:

lapply(1:3, function(r) subset(DF, Rank == r))

它返回一个列表,其组件是三个数据框。

更新:也写出了第二个解决方案。

于 2013-11-19T22:33:47.977 回答