3

大きなデータフレーム内で、別の要素のIDに基づいて、他の行からの特定のデータをグループ化する新しい行を作成しようとしています。データの例を次に示します。

> Species    Status    Value
> A         Introduced   10
> A          Native      3
> B          Crypt       6
> C         Introduced   19
> C          Native      4

種ごとに、ステータス「Introduced」または「Crypt」のデータのみを取得し、「Native」ステータスのデータを無視する新しい行を作成したいと思います。各種には、「Introduced」と「Native」のみ、または「Crypt」のみのデータがあります。

したがって、私の希望する出力は次のようになります。

> Species    Status    Value
> A         Introduced   10
> A          Native      3
> A         IC.Total     10
> B          Crypt       6
> B         IC.Total     6
> C         Introduced   19
> C          Native      4
> C         IC.Total     19

これを実行するための最良の方法はforループですか、それとももっとエレガントな方法がありますか?どんな提案も素晴らしいでしょう-あなたの助けに感謝します!

4

2 に答える 2

2

以下はdata.tableパッケージを使用しています。
元のdata.frameが呼び出されたと仮定しますmyDat

library(data.table)
myDT <- data.table(myDat, key="Species")

# Creates a new DT, of only the Speices column
myDT2 <- setkey(unique(myDT[, list(Species)]), "Species")

# Add IC.Total values
myDT2[myDT[Status=="Introduced"], c("Status", "ValueC") := list("IC.Total", Value)]

# Add Crypt values
myDT2[myDT[Status=="Crypt"], c("Status", "ValueC") := list("Crypt", Value)]

# fix the column name
setnames(myDT2, "ValueC", "Value")

# combine and sort by speicies
myDT <- setkey(rbind(myDT, myDT2), "Species")

myDT
#    Species     Status Value
# 1:       A Introduced    10
# 2:       A     Native     3
# 3:       A   IC.Total    10
# 4:       B      Crypt     6
# 5:       B      Crypt     6
# 6:       C Introduced    19
# 7:       C     Native     4
# 8:       C   IC.Total    19

cryptカウント を複製したくない場合は、上の行を削除してください。

于 2013-03-04T18:19:41.543 に答える
1

mergeおよびを使用できますaggregate(集約するものはありませんが):

merge(mydf, 
      cbind(aggregate(Value ~ Species, mydf, sum, 
                      subset = c(Status != "Native")), 
            Status = "IC.Total"),
      all = TRUE)
#   Species     Status Value
# 1       A Introduced    10
# 2       A     Native     3
# 3       A   IC.Total    10
# 4       B      Crypt     6
# 5       B   IC.Total     6
# 6       C Introduced    19
# 7       C     Native     4
# 8       C   IC.Total    19

aggregateデータをサブセット化できる便利な引数があるため、これを使用しました。この場合、「ネイティブ」には関心がありません。さらに、1つの種に対して「Introduced」と「Crypt」が一緒になることは決してなく、「Introduced」または「Crypt」の値が複数になることはないためsum、集計関数として使用することはありません。 t何かを変更します。


アップデート

このソリューションの背後にあるこの概念は、コメントにあるように複数の「値」変数がある場合でも機能しますが、以下に示すように、いくつかのわずかな変更を加える必要があります。

まず、いくつかのデータを作成しましょう。

mydf <- data.frame(
  Species = c("A", "A", "B", "C", "C"),
  Status = c("Introduced", "Native", "Crypt", "Introduced", "Native"),
  Value1 = c(10, 3, 6, 19, 4),
  Value2 = c(6, 8, 12, 19, 5),
  Value3 = c(18, 19, 14, 13, 2))
mydf
#   Species     Status Value1 Value2 Value3
# 1       A Introduced     10      6     18
# 2       A     Native      3      8     19
# 3       B      Crypt      6     12     14
# 4       C Introduced     19     19     13
# 5       C     Native      4      5      2

次に、aggregatemergeを以前と同じように使用しますが、わずかな違いに注意してください。まず、subset以前の方法を使用できないため、データセット全体を集計する代わりに、関心のある行のみを集計します。次に、グループ化変数として「ステータス」を追加しました。データの現在の構造として説明したものと、結果に違いはありません。第3に、集計後、[ステータス]列を削除し、新しいステータス列を追加する必要があります(これが、[-2]コードが実行していることです。2番目の列を削除します)。

これが、すべて1つの整頓されたパッケージに含まれています。

merge(mydf, 
      cbind(aggregate(. ~ Species + Status, 
                      mydf[mydf$Status != "Native", ], sum)[-2], 
            Status = "IC.Total"),
      all = TRUE)
#   Species     Status Value1 Value2 Value3
# 1       A Introduced     10      6     18
# 2       A     Native      3      8     19
# 3       A   IC.Total     10      6     18
# 4       B      Crypt      6     12     14
# 5       B   IC.Total      6     12     14
# 6       C Introduced     19     19     13
# 7       C     Native      4      5      2
# 8       C   IC.Total     19     19     13
于 2013-03-04T18:20:39.890 に答える