web-dev-qa-db-ja.com

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を含むベクトルがあります)。

1つのレベルの最初の要素に到達することが可能です。

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

ただし、すべてのレベルで機能するわけではありません。

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

どうしますか?

さらに、データフレームを変更して、発生するたびに各レベルの最初の要素がどれであるかを確認したいと思います。私の例では、新しい列は次のようになります。

  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
20
hadrienj

関数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
6
sparrow

編集。私の答えの最初の部分は、元の質問、つまりbefore "そしてさらに進むために」(これは編集でOPによって追加されました)。

別の可能性として、duplicatedを使用します。 _?duplicated_から: "duplicated()は、ベクトルまたはデータフレームのどの要素が、より小さな添え字を持つ要素の複製であるかを判別します。"

ここでは、論理否定(NOT)である_!_を使用して、「n」の重複要素not、つまり各レベルの最初の要素を選択します。 'n'の。

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

更新これまで「さらに進む」編集は表示されませんでした。私の最初の提案は、@ thelatemailと@sparrowによってすでに提案されているように、間違いなくaveを使用することです。しかし、Rツールボックスを掘り下げて別の方法を示すために、ここにdplyrの方法があります。

データをnでグループ化し、mutate関数を使用して、値「sの最初の要素」(_s[1]_)を持つ新しい変数「first」を作成します。

_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便利な関数を使用して、_[1]_の代わりにfirstを使用します。

_df %.%
  group_by(n) %.%
  mutate(
    first = first(s))
_

元の質問に対するdplyrの解決策は、summariseを使用することです。

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

#   n first
# 1 2     a
# 2 3     c
# 3 4     e
_
16
Henrik

matchを使用したアプローチは次のとおりです。

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

編集:多分これは少し混乱しているように見えます...

最初の要素をリストする列を取得するには、matchを2回使用できます(ただし、xtableの引数を入れ替えます)。

 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
11
sgibb

この場合、私はplyrパッケージを好みます。これにより、データをさらに自由に操作できます。

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

  n s
1 2 a
2 3 c
3 4 e
4
Chitrasen

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の値を取得し、それを新しい列に割り当てるだけです。

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

あなたの問題は、2つのベクトルを比較していることだと思います。df$ nはベクトルで、levels(n)はベクトルです。 vector == df $ nはlevels(n)の倍数であるため、vectorはたまたま機能します。

2
Andrew Cassidy

回答ストリームにこのクラシックがまだ表示されていないことに驚いています。

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