我有一个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
问题:从输入数据框中,我只想从每个组中选择最高的两个标记值,称为MONTH和COUNTRY。样本输出如上所示。
任何人都可以共享示例代码以生成正确的输出并将其分配给新的数据帧。任何方法都是可取的,包括sqldf
。
答案 0 :(得分:2)
您可以使用data.table
按以下方式执行此操作。感谢@Arun提出的改进答案的建议。
require(data.table)
dat <- fread(txt)
dat[order(MARKS), tail(.SD, 2L), by=c("MONTH", "COUNTRY")]
请注意,这仅计算顺序向量,并且在执行分组操作之前不会重新排列整个data.table(因此内存效率更高)。 .SD
包含每个组的数据子集,本身就是data.table。
如果组太多,tail(.SD, 2L)
可能稍微慢一些,在这种情况下,我们可以使用返回索引的.I
,然后最后一次执行子集,如下所示:
ix = dat[order(MARKS), .(I=tail(.I, 2L)), by=c("MONTH", "COUNTRY")][, I]
dat[ix]
这导致:
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
是您的数据,而不是结尾.
txt <- "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"
答案 1 :(得分:1)
在dplyr中,您可以group_by
,arrange
和slice
。有些清洁:
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
答案 2 :(得分:0)
以下是base R
的选项(未使用任何包)。我们使用substr
从'MONTH'中提取前3个字母(因为在某些情况下有一些.
)。使用ave
,我们根据{COUNTRY'和'MONTH'分组后的rank
得到逻辑索引,它可用于对行进行子集化。
df1$MONTH <- substr(df1$MONTH, 1, 3)
df1[with(df1, as.logical(ave(MARKS, COUNTRY, MONTH,
FUN = function(x) rank(-x) %in% 1:2))),]