закажите два столбца, условно выберите значения, затем запустите cumsum frequency


Мои данные выглядят так

a   b   c
1   1   0
1   2   8
2   1   0
2   2   2
3   1   3
3   2   3
4   1   7
4   2   4
5   1   3
5   2   5
6   1   1
6   2   8
7   1   1
7   2   2

Я хочу отсортировать столбцы a и c так, чтобы каждая четная строка в столбце c была наибольшим числом для каждой пары в столбце A. Затем я хочу взять эти значения и сохранить их в новом объекте. Это должно выглядеть примерно так.

a   c   b
1   8   2
2   2   2
3   3   2
4   7   1
5   5   2
6   8   2
7   2   2
4 4

4 ответа:

С помощью пакета data.table Вы можете сортировать данные по ссылке с помощью setorder или setkey (без необходимости создавать копии с помощью функции <-)

library(data.table)
setorder(setDT(df), a, c)[]
#     a b c
#  1: 1 1 0
#  2: 1 2 8
#  3: 2 1 0
#  4: 2 2 2
#  5: 3 1 3
#  6: 3 2 3
#  7: 4 1 7
#  8: 4 2 4
#  9: 5 1 3
# 10: 5 2 5
# 11: 6 1 1
# 12: 6 2 8
# 13: 7 1 1
# 14: 7 2 2
Тогда вы можете достичь своей цели различными простыми способами, например
df[duplicated(a)]
#    a b c
# 1: 1 2 8
# 2: 2 2 2
# 3: 3 2 3
# 4: 4 2 4
# 5: 5 2 5
# 6: 6 2 8
# 7: 7 2 2

Или, может быть,

df[, tail(.SD, 1), a]
#    a b c
# 1: 1 2 8
# 2: 2 2 2
# 3: 3 2 3
# 4: 4 2 4
# 5: 5 2 5
# 6: 6 2 8
# 7: 7 2 2

Или

df[, .SD[2], a]
#    a b c
# 1: 1 2 8
# 2: 2 2 2
# 3: 3 2 3
# 4: 4 2 4
# 5: 5 2 5
# 6: 6 2 8
# 7: 7 2 2
P.S. Если вы хотите изменить порядок столбцов , вы также можете сделать это с помощью ссылки, используя функцию setcolorder, например,
setcolorder(df, c("a", "c", "b"))

Вы можете использовать такой подход:

dat[order(dat$a, dat$c), ][c(FALSE, TRUE), ]
#    a b c
# 2  1 2 8
# 4  2 2 2
# 6  3 2 3
# 7  4 1 7
# 10 5 2 5
# 12 6 2 8
# 14 7 2 2

Альтернативный подход с dplyr:

library(dplyr)
dat %>%
  arrange(a, c) %>%
  filter(duplicated(a))

Вот один из способов. Если ваши данные уже расположены так, как df, я бы сделал slice(group_by(mydf, a), 2), используя dplyr. Но я не уверен, что это так. Я создал образец и сделал следующее. Когда есть ничья в c, Вы, кажется, также рассматриваете b; Вы взяли ряд с max(b). Так что, я думаю, это, вероятно, один из способов пойти.

library(dplyr)
foo <- data.frame(a = c(1, 1, 2, 2, 3, 3, 4, 4, 5, 5),
                  b = c(3, 5, 5, 6, 7, 1, 7, 3, 9, 2),
                  c = c(4, 0, 2, 6, 7, 7, 5, 2, 8, 1))
#   a b c
#1  1 3 4
#2  1 5 0
#3  2 5 2
#4  2 6 6
#5  3 7 7
#6  3 1 7
#7  4 7 5
#8  4 3 2
#9  5 9 8
#10 5 2 1

group_by(arrange(foo, a, c, b), a) %>%
slice(2)

#  a b c
#1 1 3 4
#2 2 6 6
#3 3 7 7
#4 4 7 5
#5 5 9 8

Если я правильно понимаю вашу проблему, это решение должно соответствовать вашим потребностям:

### Sample data
a <- rep(1:7, each = 2)
b <- rep(1:2, length(a)/2)
c <- c(0, 8, 0, 2, 3, 3, 7, 4, 3, 5, 1, 8, 1, 2)

abc <- cbind(a, b, c)


### Identify unique values of 'a'
unique_a <- unique(abc[, 1])

# Loop over all unique values of 'a'
t(sapply(unique_a, function(i) {

  # Subset data by current unique entry
  tmp_abc <- abc[which(abc[, 1] == i), ]

  # Extract corresponding values of 'c'
  tmp_val_c <- tmp_abc[, 3]

  # If all values of 'c' are equal, take the 2nd entry (i.e. row)
  if (tmp_val_c[1] == tmp_val_c[2]) {
    id_max <- 2
  # Else, identify the row with the maximum value of 'c'   
  } else {
    id_max <- which.max(tmp_abc[, 3])
  }

  # Return row holding maximum value of 'c'
  return(tmp_abc[id_max, c(1, 3, 2)])
}))

Соответствующее возвращаемое значение выглядит следующим образом:

     a c b
[1,] 1 8 2
[2,] 2 2 2
[3,] 3 3 2
[4,] 4 7 1
[5,] 5 5 2
[6,] 6 8 2
[7,] 7 2 2