只需要通过在R中对数据帧的两列进行分组来获取前两个最高的记录

只需要通过在R中对数据帧的两列进行分组来获取前两个最高的记录,r,dataframe,R,Dataframe,我有一个data.frame,它包含4列13行。下面是示例数据。[列名为大写,数据为小写] 示例输入数据: NAME. MARKS MONTH COUNTRY ram 20. jan India ranjith 40. jan India naren. 80. jan. India Amir. 90. feb. India kumar. 60. feb India azhar 80. feb India mark

我有一个data.frame,它包含4列13行。下面是示例数据。[列名为大写,数据为小写]

示例输入数据:

NAME.  MARKS  MONTH COUNTRY
ram       20. jan   India
ranjith   40.  jan   India
naren.    80.  jan.  India
Amir.     90.  feb.   India
kumar.    60.  feb     India
azhar     80.  feb   India
mark      90.  feb.  US
Alex.     55   feb.  US
chris     20   feb   US
rakesh    60.  jan   US
Mona.     70.   jan.  US
mano.     90.  mar.   UK
Ron.       37.  mar.  UK
预期产出:

NAME    MARKS. MONTH  COUNTRY
naren    80.    jan.    India
ranjith  40.    jan.    India
Amir.    90.    feb.    India
Azhar.   80.    feb.    India
mark.    90.    feb.     US
Alex     55.    feb.     US
Mona.    70.    jan.     US
Rakesh.   60.    jan.    US
mano.     90.    mar.    UK
Ron.      37.    mar.    UK
问题:从输入数据框中,我只想从每个名为“月”和“国家”的组中选择最高的两个标记值。上面给出了示例输出


任何人都可以共享示例代码以生成正确的输出并将其分配给新的数据帧。包括sqldf在内的任何方法都是可取的。

您可以使用data.table如下所示。感谢@Arun对改进答案的建议

require(data.table)
dat <- fread(txt)
dat[order(MARKS), tail(.SD, 2L), by=c("MONTH", "COUNTRY")]
这导致:

    MONTH COUNTRY    NAME MARKS
 1:   jan   India ranjith    40
 2:   jan   India   naren    80
 3:   feb   India   kumar    60
 4:   feb   India   azhar    80
 5:   feb      US    Alex    55
 6:   feb      US   chris    20
 7:   feb   India  rakesh    60
 8:   feb   India    Mona    70
 9:   mar      UK    mano    90
10:   mar      UK     Ron    37
其中txt是不带结尾的数据

在dplyr中,您可以按分组、排列和切片。进行一些清洁:

library(dplyr)

       # take out .s
df %>% mutate_all(sub, pattern = '.', replacement = '', fixed = TRUE) %>% 
  # convert to numbers, if necessary
  mutate_all(type.convert, as.is = TRUE) %>% 
  # set grouping for following operations
  group_by(MONTH, COUNTRY) %>% 
  # sort by MARKS, descending
  arrange(desc(MARKS)) %>%
  # subset to top two rows of each group
  slice(1:2)

## Source: local data frame [10 x 4]
## Groups: MONTH, COUNTRY [5]
## 
##      NAME. MARKS MONTH COUNTRY
##      <chr> <int> <chr>   <chr>
## 1     Amir    90   feb   India
## 2    azhar    80   feb   India
## 3     mark    90   feb      US
## 4     Alex    55   feb      US
## 5    naren    80   jan   India
## 6  ranjith    40   jan   India
## 7     Mona    70   jan      US
## 8   rakesh    60   jan      US
## 9     mano    90   mar      UK
## 10     Ron    37   mar      UK
这是一个没有使用包的基本R选项。我们使用substr从“月”中提取前3个字母,因为其中有一些字母。在某些情况下。使用ave,我们根据“国家”和“月份”分组后的排名得到逻辑索引,它可以用来子集行

df1$MONTH <- substr(df1$MONTH, 1, 3)
df1[with(df1, as.logical(ave(MARKS, COUNTRY, MONTH,
                    FUN = function(x) rank(-x) %in% 1:2))),]

除非它们是一致的,否则你的.s会把分组搞得一团糟。另外,它使你的数字看起来可能是字符串,而不是实际的数字。Alistaire..我手动输入的那些数字没有粘贴。所以请忽略输入错误。把这些数字当作“忽略”,谢谢你的回应,上面的代码也会生成名字列吗?因为我的输出需要全部4列。我不确定数据是否按照tail选择正确行的顺序排序。现在,我认为这是正确的继续=分数。。。这是错的吗?它应该按标记排序,然后按=…@Arun分组,谢谢你的评论。因此,也许我确实理解了一些错误:setkey keys=对data.table进行排序。二级索引应该在没有排序的情况下执行类似的操作。因此,我如何在运行中对数据进行排序。例如,表按标记排序,然后按=。。。。因此,j.e.g.SD中的数据按标记排序,并按。。。我认为这也是on可以使用的。所以Arun建议的代码将用于此问题?使用order函数根据标记进行排序,然后使用fiven tail函数仅拾取最后2个值,然后使用2列c进行分组。请确认once@Arun:谢谢你的解释。刚刚编辑了答案。谢谢Alistaire..我会实施它并与您分享详细信息..我会随时通知您
library(dplyr)

       # take out .s
df %>% mutate_all(sub, pattern = '.', replacement = '', fixed = TRUE) %>% 
  # convert to numbers, if necessary
  mutate_all(type.convert, as.is = TRUE) %>% 
  # set grouping for following operations
  group_by(MONTH, COUNTRY) %>% 
  # sort by MARKS, descending
  arrange(desc(MARKS)) %>%
  # subset to top two rows of each group
  slice(1:2)

## Source: local data frame [10 x 4]
## Groups: MONTH, COUNTRY [5]
## 
##      NAME. MARKS MONTH COUNTRY
##      <chr> <int> <chr>   <chr>
## 1     Amir    90   feb   India
## 2    azhar    80   feb   India
## 3     mark    90   feb      US
## 4     Alex    55   feb      US
## 5    naren    80   jan   India
## 6  ranjith    40   jan   India
## 7     Mona    70   jan      US
## 8   rakesh    60   jan      US
## 9     mano    90   mar      UK
## 10     Ron    37   mar      UK
df1$MONTH <- substr(df1$MONTH, 1, 3)
df1[with(df1, as.logical(ave(MARKS, COUNTRY, MONTH,
                    FUN = function(x) rank(-x) %in% 1:2))),]