1

3つの列で構成されるデータフレームがあります(コードの例を参照)。最初の列にはカテゴリ(a)が含まれ、2番目の列には観測値の数(b)が含まれ、3番目の列にはこれらの観測値の平均値(c)が含まれます。

    #create a test df
    a<-factor(c("aaa","aaa","aaa","ddd","eee","ddd","aaa","ddd"))
    b<-c(3,4,1,3,5,7,3,2)
    c<-c(1,2,NA,4,5,6,7,NA)
    df.abc<-data.frame(a=a,b=b,c=c)
    df.abc

観測数が1または2の場合、欠測値(NA)としてマークされたエントリ。

したがって、私の関数の目的は、これらの欠落値を各カテゴリの平均値で置き換えることです。

しばらく時間がかかりましたが、1つのカテゴリのすべての欠落値を置き換える関数が機能しました(観測値が1の場合)。次のようになります。

    #function to substitue the missing values in row c by their means 
    #according to their categories
    function.abc<-function(x){
        ifelse(
            (df.abc[,1]==x)&(df.abc[,2]==1),
            mean(df.abc$c[df.abc$a ==x],na.rm=TRUE),
            df.abc[,3]
        )
    }

この機能のテスト:

    #test the function for the category "ccc"
    function.abc("aaa")

これは非常にうまく機能します(ただし、平均ではなく平均にすぎません)。出力は次のとおりです。

[1] 1.000000 2.000000 3.333333 4.000000 5.000000 6.000000 7.000000 NA

今私の問題は、私が非常に多くのカテゴリ(n = 32)を持っていることであり、この関数を私のカテゴリを含むベクトルに適用しようとしました。この場合の簡単な例は次のとおりです。

    #test the function for a testvector
    test.vector<-c("aaa","ddd")
    function.abc(test.vector)

出力は次のとおりです。

[1] 1.0 2.0 4.5 4.0 5.0 6.0 7.0 NA

だから明らかにこれはうまくいきません...

誰かが私が機能を再配置するのを手伝ってもらえますか?私はプログラミングにまったく慣れていませんが、短くてうまく機能する関数を設計することはまだ大きな課題です...

編集:

出力を次のようにします:[1] 1.000000 2.000000 3.20000 4.000000 5.000000 6.000000 7.000000 5.000000

そのため、グループaaaの平均(3.20000)がaaaのNA値に置き換わり、グループdddの平均(5.0000000)がdddのNAに置き換わります。

4

3 に答える 3

1

カテゴリ内で一度に複数の列を操作するには、データフレームを分割してからコンポーネントを操作するものを使用する必要があります。このlapply( split(df, fac), function(x) {...})パラダイムはこれに適しています。transformまたは、またはplyrパッケージを使用できます。

> lapply( split( df.abc, df.abc$a), 
               function(dfrm) { dfrm[is.na(dfrm$c), "c"] <- 
                  weighted.mean(dfrm[!is.na(dfrm$c) , "c"], dfrm[!is.na(dfrm$c), "b"])
                         dfrm} )  
                # need to evaluate dfrm in order to return the full value.
$aaa
    a b   c
1 aaa 3 1.0
2 aaa 4 2.0
3 aaa 1 3.2
7 aaa 3 7.0

$ddd
    a b   c
4 ddd 3 4.0
6 ddd 7 6.0
8 ddd 2 5.4

$eee
    a b c
5 eee 5 5

rbindその後、 `do.callを使用してそれらを行うことができます:

 do.call( rbind, lapply( split( df.abc, df.abc$a), 
          function(dfrm) { dfrm[is.na(dfrm$c), "c"] <-
                 weighted.mean(dfrm[!is.na(dfrm$c) , "c"], dfrm[!is.na(dfrm$c), "b"])
                   dfrm} ) )
        a b   c
aaa.1 aaa 3 1.0
aaa.2 aaa 4 2.0
aaa.3 aaa 1 3.2
aaa.7 aaa 3 7.0
ddd.4 ddd 3 4.0
ddd.6 ddd 7 6.0
ddd.8 ddd 2 5.4
eee   eee 5 5.0
于 2012-11-21T17:50:56.803 に答える
0

意味がよくわかりませんが、そのような行をすべて含める場合は、%in%を使用できます。

function.abc<-function(x){
  ifelse(
    (df.abc[,1] %in% x)&(df.abc[,2]==1),
    mean(df.abc$c[df.abc$a %in% x],na.rm=TRUE),
    df.abc[,3]
  )
}

> function.abc("aaa")
[1] 1.000000 2.000000 3.333333 4.000000 5.000000 6.000000 7.000000       NA

> test.vector<-c("aaa","ddd")
> function.abc(test.vector)
[1]  1  2  4  4  5  6  7 NA

列'b'は1ではないため、最後の要素はNAです。

于 2012-11-21T17:17:49.327 に答える
0

CatMeans <- tapply(df.abc$c, df.abc$a, function(x) mean(x, na.rm==T))カテゴリ別の手段を取得します。

     aaa      ddd      eee 
3.333333 5.000000 5.000000 

それで、それらすべてのためにそれをします:

> CatMeans <- tapply(df.abc$c, df.abc$a, function(x) mean(x, na.rm==T))
> ifelse(is.na(df.abc$c), CatMeans[df.abc$a], df.abc$c)
[1] 1.000000 2.000000 3.333333 4.000000 5.000000 6.000000 7.000000 5.000000

あなたはそれを私が確信している関数にすることができます。"aaa"とだけが必要な場合"ddd"は、ifelse(is.na(df.abc$c) & df.abc$a %in% c("aaa","ddd"),...

于 2012-11-21T17:22:24.557 に答える