Подтвердить что ты не робот

В R, как я могу получить доступ к первому элементу каждого уровня фактора?

У меня есть такой кадр данных:

n = c(2, 2, 3, 3, 4, 4) 
n <- as.factor(n)
s = c("a", "b", "c", "d", "e", "f") 
df = data.frame(n, s)  

df
  n s
1 2 a
2 2 b
3 3 c
4 3 d
5 4 e
6 4 f

и я хочу получить доступ к первому элементу каждого уровня моего множителя (и иметь в этом примере вектор, содержащий a, c, e).

Можно достигнуть первого элемента одного уровня, с

df$s[df$n == 2][1]

но он не работает для всех уровней:

df$s[df$n == levels(n)]
[1] a f

Как вы это сделаете?

И чтобы идти дальше, Id хотел бы изменить свой фрейм данных, чтобы увидеть, какой из них является первым элементом для каждого уровня в каждом случае. В моем примере новый столбец должен быть:

  n s rep firstelement
1 2 a   a            a
2 2 b   c            a
3 3 c   e            c
4 3 d   a            c
5 4 e   c            e
6 4 f   e            e
4b9b3361

Ответ 1

функция ave полезна в этих случаях:

df$firstelement = ave(df$s, df$n, FUN = function(x) x[1])
df
  n s firstelement
1 2 a            a
2 2 b            a
3 3 c            c
4 3 d            c
5 4 e            e
6 4 f            e

Ответ 2

Edit. В первой части моего ответа рассматривается исходный вопрос, т.е. До "И идти дальше" (который был добавлен OP в редактировании).

Другая возможность, используя duplicated. Из ?duplicated: "duplicated() определяет, какие элементы вектора или фрейма данных являются дубликатами элементов с меньшими индексами."

Здесь мы используем !, логическое отрицание (NOT), чтобы выбрать не дублированные элементы "n", то есть первые элементы каждого уровня "n".

df[!duplicated(df$n), ]
#   n s
# 1 2 a
# 3 3 c
# 5 4 e

Обновить Не видел до сих пор вашего редактирования "И идти дальше". Мое первое предложение, безусловно, было бы использовать ave, как уже было предложено @thelatemail и @sparrow. Но просто чтобы копаться в панели инструментов R и показать вам альтернативу, здесь dplyr способ:

Группируйте данные с помощью n, используйте функцию mutate для создания новой переменной "first" со значением "first element of s" (s[1]),

library(dplyr)

df %.%
  group_by(n) %.%
  mutate(
    first = s[1])
#   n s first
# 1 2 a     a
# 2 2 b     a
# 3 3 c     c
# 4 3 d     c
# 5 4 e     e
# 6 4 f     e

Или включите функции удобства dplyr и используйте first вместо [1]:

df %.%
  group_by(n) %.%
  mutate(
    first = first(s))

A dplyr решение для вашего исходного вопроса будет состоять в использовании summarise:

df %.%
  group_by(n) %.%
  summarise(
    first = first(s))

#   n first
# 1 2     a
# 2 3     c
# 3 4     e

Ответ 3

Вот подход с использованием match:

 df$s[match(levels(n), df$n)]

EDIT: Может быть, это выглядит немного запутанным...

Чтобы получить столбец, в котором перечислены первые элементы, вы можете дважды использовать match (но с заменой x и table):

 df$firstelement <- df$s[match(levels(n), df$n)[match(df$n, levels(n))]]
 df$firstelement
 # [1] a a c c e e
 # Levels: a b c d e f

Давайте рассмотрим это подробно:

 ## this returns the first matching elements
 match(levels(n), df$n)
 # [1] 1 3 5

 ## when we swap the x and table argument in match we get the level index
 ## for each df$n (the duplicated indices are important)
 match(df$n, levels(n))
 # [1] 1 1 2 2 3 3

 ## results in
 c(1, 3, 5)[c(1, 1, 2, 2, 3, 3)]
 # [1] 1 1 3 3 5 5
 df$s[c(1, 1, 3, 3, 5, 5)]
 # [1] a a c c e e
 # Levels: a b c d e f

Ответ 4

В этом случае я предпочитаю пакет plyr, он дает дополнительную свободу для обработки данных.

library(plyr)
ddply(df,.(n),function(subdf){return(subdf[1,])})

  n s
1 2 a
2 3 c
3 4 e

Ответ 5

Вы также можете использовать data.table

library(data.table)
dt = as.data.table(df)
dt[, list(firstelement = s[1]), by=n]

который доставит вас:

   n firstelement
1: 2            a
2: 3            c
3: 4            e

Бит by=n группирует все по каждому значению n, поэтому s[1] получает первый элемент каждой из этих групп.

Чтобы получить это как дополнительный столбец, вы можете сделать:

dt[, newcol := s[1], by=n]
dt
#   n s newcol
#1: 2 a      a
#2: 2 b      a
#3: 3 c      c
#4: 3 d      c
#5: 4 e      e
#6: 4 f      e

Итак, это просто принимает значение s из первой строки каждой группы и присваивает ее новому столбцу.

Ответ 6

df$s[sapply(levels(n), function(particular.level) { which(df$n == particular.level)[1]})]

Я считаю, что ваша проблема в том, что вы сравниваете два вектора. df $n - вектор, а уровни (n) - вектор. vector == вектор работает только для вас, так как df $n - это множественная длина уровней (n)

Ответ 7

Удивлен не видеть эту классику в потоке ответов еще.

> do.call(rbind, lapply(split(df, df$n), function(x) x[1,]))
##   n s
## 2 2 a
## 3 3 c
## 4 4 e