3

私はそのようなデータを持っています:

object category country
495647 1        RUS  
477462 2        GER  
431567 3        USA  
449136 1        RUS  
367260 1        USA  
495649 1        RUS  
477461 2        GER  
431562 3        USA  
449133 2        RUS  
367264 2        USA  
...

1 つのオブジェクトがさまざまな(category, country)ペアで表示され、国が 1 つのカテゴリ リストを共有します。

それに別の列を追加したいと思います。これは、国ごとのカテゴリの重みになります。カテゴリのカテゴリに表示されるオブジェクトの数は、国内で合計が 1 になるように正規化されます (一意の(category, country)ペアのみの合計)。

私は次のようなことができます:

aggregate(df$object, list(df$category, df$country), length)

そこから重みを計算しますが、元のデータで直接それを行うより効率的でエレガントな方法は何ですか.

望ましい出力例:

object category country weight
495647 1        RUS     .75
477462 2        GER     .5 
431567 3        USA     .5 
449136 1        RUS     .75
367260 1        USA     .25
495649 1        RUS     .75
477461 3        GER     .5
431562 3        USA     .5
449133 2        RUS     .25
367264 2        USA     .25
...

(category, country)上記は、一意のペアの国内で合計されます。

4

3 に答える 3

3

「元のデータに対して直接それを行うためのより効率的でエレガントな方法は何ですか。」という最後の文を念頭に置いて具体的に応答すると、data.tableこのための新しい機能があります。

install.packages("data.table", repos="http://R-Forge.R-project.org")
# Needs version 1.8.1 from R-Forge.  Soon to be released to CRAN.

あなたのデータを使ってDT

> DT[, countcat:=.N, by=list(country,category)]     # add 'countcat' column
    category country countcat
 1:        1     RUS        3
 2:        2     GER        1
 3:        3     USA        2
 4:        1     RUS        3
 5:        1     USA        1
 6:        1     RUS        3
 7:        3     GER        1
 8:        3     USA        2
 9:        2     RUS        1
10:        2     USA        1

> DT[, weight:=countcat/.N, by=country]     # add 'weight' column
    category country countcat weight
 1:        1     RUS        3   0.75
 2:        2     GER        1   0.50
 3:        3     USA        2   0.50
 4:        1     RUS        3   0.75
 5:        1     USA        1   0.25
 6:        1     RUS        3   0.75
 7:        3     GER        1   0.50
 8:        3     USA        2   0.50
 9:        2     RUS        1   0.25
10:        2     USA        1   0.25

:=データを参照して列を追加し、「古い」機能です。新機能は、グループごとに機能するようになったことです。 .N各グループの行数を保持する記号です。

これらの操作はメモリ効率が高く、大規模なデータに拡張する必要があります。たとえば、1e81e9

中間列を含めたくない場合は、countcat後で削除してください。繰り返しになりますが、これはテーブルのサイズに関係なく(ポインターを内部で移動することにより)即座に機能する効率的な操作です。

> DT[,countcat:=NULL]     # remove 'countcat' column
    category country weight
 1:        1     RUS   0.75
 2:        2     GER   0.50
 3:        3     USA   0.50
 4:        1     RUS   0.75
 5:        1     USA   0.25
 6:        1     RUS   0.75
 7:        3     GER   0.50
 8:        3     USA   0.50
 9:        2     RUS   0.25
10:        2     USA   0.25
> 
于 2012-06-18T12:59:59.067 に答える
2

実は少し前に似たような質問をしました。data.table はこれに非常に適しています。特に、:= by group が実装され、上記のように自己結合が不要になったためです。ベース R からの最適解は ですave()tapply()も使用できます。

これは、 を使用した上記のソリューションに似ていave()ます。ただし、data.table を確認することを強くお勧めします。

df$count <- ave(x = df$object, df$country, df$category, FUN = length)
df$weight <- ave(x = df$count, df$country, FUN = function(x) x/length(x))
于 2012-06-18T15:07:27.370 に答える
1

1行でそれを行うための読みやすい方法がわかりません。しかし、それはかなりコンパクトにすることができます。

# Use table to get the counts.
counts <- table(df[,2:3])
# Normalize the table
weights <- t(t(counts)/colSums(counts))
# Use 'matrix' selection by names.
df$weight <- weights[as.matrix(df[,2:3])]
于 2012-06-18T13:18:11.920 に答える