I have a dataset "df"
> df
A B C
1 tanu abc 10
2 tanu def 20
3 tanu ghi 15
4 tanu jkl 28
5 tanu mno 33
6 tanu pqr 46
7 tanu stu 83
8 tanu vwx 15
9 edu yz1 60
10 edu abc2 85
> group
[1] 3 2 3 2
I have to find the maximum value of column "C" for each group. Each group is groupby column "A" containing corresponding number of rows from vector "group"
Group1:
tanu abc 10
tanu def 20
tanu ghi 15
Group2:
tanu jkl 28
tanu mno 33
Group3:
tanu pqr 46
tanu stu 83
tanu vwx 15
Group4:
edu yz1 60
edu abc2 85
I was not able to achieve this by aggregate
or by
function. I want my output be
> out
A B C
tanu def 20
tanu mno 33
tanu stu 83
edu abc2 85
Appreciate any help. TIA.
Another base R way with by
and which.max
:
do.call(rbind,
by(df, list(rep(seq_along(group), group)), function(g) g[which.max(g$C),]))
# A B C
# 1 tanu def 20
# 2 tanu mno 33
# 3 tanu stu 83
# 4 edu abc2 85
At first, I thought it was the maximum or C
column and the min
value based on the group
for B
variable. Below is the solution based on that.
library(data.table)
res <- setDT(df)[, list(B=B[min(group)], C=max(C)),
by=list(gr=rep(seq_along(group), group),A)][,gr:=NULL]
After looking @Matthew Plourde's solution, it became evident that I was wrong (in the example, both produce the same result). In that case,
res <- setDT(df)[df[, max(C)==C,
by=list(rep(seq_along(group), group), A)]$V1]
res
# A B C
#1: tanu def 20
#2: tanu mno 33
#3: tanu stu 83
#4: edu abc2 85
Or using dplyr
library(dplyr)
df %>%
group_by(gr=rep(seq_along(group), group), A) %>%
filter(C==max(C))%>%
ungroup() %>%
select(-gr)
# A B C
#1 tanu def 20
#2 tanu mno 33
#3 tanu stu 83
#4 edu abc2 85
df <- structure(list(A = c("tanu", "tanu", "tanu", "tanu", "tanu",
"tanu", "tanu", "tanu", "edu", "edu"), B = c("abc", "def", "ghi",
"jkl", "mno", "pqr", "stu", "vwx", "yz1", "abc2"), C = c(10L,
20L, 15L, 28L, 33L, 46L, 83L, 15L, 60L, 85L)), .Names = c("A",
"B", "C"), class = "data.frame", row.names = c("1", "2", "3",
"4", "5", "6", "7", "8", "9", "10"))
I think this will also do it.
s <- sapply(split(df$C, rep.int(seq_along(group), group)), which.max)
df[s + cumsum(c(0, group[-length(group)])), ]
# A B C
# 2 tanu def 20
# 5 tanu mno 33
# 7 tanu stu 83
# 10 edu abc2 85
This might not be the clearest answer but it works :)
A = c("tanu",
"tanu",
"tanu",
"tanu",
"tanu",
"tanu",
"tanu",
"tanu",
"edu",
"edu")
B = c("abc",
"def",
"ghi",
"jkl",
"mno",
"pqr",
"stu",
"vwx",
"yz1",
"abc2")
C = c(10,20,15,28,33,46,83,15,60,85)
df = data.frame(A=A, B=B, C=C)
group = c(3,2,3,2)
out = NULL
line.nb = 1
for(i in 1:length(group)){
beg = line.nb
end = line.nb + group[i]-1
temp = df[beg:end,]
res = temp[which(temp[,"C"] ==max(temp[,"C"])), ]
out = rbind(out,res)
line.nb = line.nb+group[i]
}
out
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.