Ответ 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
У меня есть такой кадр данных:
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
функция 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
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
Вот подход с использованием 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
В этом случае я предпочитаю пакет plyr, он дает дополнительную свободу для обработки данных.
library(plyr)
ddply(df,.(n),function(subdf){return(subdf[1,])})
n s
1 2 a
2 3 c
3 4 e
Вы также можете использовать 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
из первой строки каждой группы и присваивает ее новому столбцу.
df$s[sapply(levels(n), function(particular.level) { which(df$n == particular.level)[1]})]
Я считаю, что ваша проблема в том, что вы сравниваете два вектора. df $n - вектор, а уровни (n) - вектор. vector == вектор работает только для вас, так как df $n - это множественная длина уровней (n)
Удивлен не видеть эту классику в потоке ответов еще.
> do.call(rbind, lapply(split(df, df$n), function(x) x[1,]))
## n s
## 2 2 a
## 3 3 c
## 4 4 e