2016-09-23 13 views
0

私は18枚のデータフレームのリストに、このような構造を通じて行とランダムな空白行の数が異なる各1、持っている:選択行

l = c("D1", "D1", "D1", "", "D1", "D1", "D1", "D2", "D2", "D2", "D2", "", "D3", "D3", "D3", "D3") 
    a = c("Al", "Al", "St", "", "St", "Un", "St", "Al", "Al", "St", "St", "", "Al", "Al", "St", "St") 
    b = c(6000, 4980, 123, "", 98, 87, 51, 10989, 8756, 457, 233, "", 989, 743, 67, 55) 
    mydf = data.frame("Location" = l, "Name" = a, "count" = b) 
    mydf 
     Location Name count 
1  D1 Al 6000 
2  D1 Al 4980 
3  D1 St 123 
4      
5  D1 St 98 
6  D1 Un 87 
7  D1 St 51 
8  D2 Al 10989 
9  D2 Al 8756 
10  D2 St 457 
11  D2 St 233 
12      
13  D3 Al 989 
14  D3 Al 743 
15  D3 St 67 
16  D3 St 55 

18個のデータフレームとマイデータ:

sapply(mydata, dim) 
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12] [,13] [,14] [,15] [,16] [,17] [,18] 
[1,] 171 146 132 147 149 148 138 143 114 111 115 101 112 218 122 96 156 128 
[2,] 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 

私は、Alの合計が場所ごとにカウントして私のデータフレームに列を追加するtransformを使用したいです。新しい列全体を同じ値で埋めることを計画しています。文字列 "Al"を含む行を見つけてからsum関数を適用できると思っていましたが、これは動作しません。ここに私が使用しようとしているコードはあります:

add.al.sum = function(df){ 
    als = df[grep("Al", df$Name),] 
    alsum = sum(als, na.rm = TRUE) 
    transform(df, Al.sum = c(alsum)) 
} 
mydf = lapply(mydf, function(x) add.al.sum(x)) 

これは私がしたいことをしません。変換されたデータテーブルをこのようにしたい。 空白行を保持する必要はありません

Location Name count Al.sum 
1  D1 Al 6000  10980 
2  D1 Al 4980  10980 
3  D1 St 123  10980 
4       NA 
5  D1 St 98  10980 
6  D1 Un 87  10980 
7  D1 St 51  10980 
8  D2 Al 10989  19745 
9  D2 Al 8756  19745 
10  D2 St 457  19745 
11  D2 St 233  19745 
12       NA 
13  D3 Al 989  1732 
14  D3 Al 743  1732 
15  D3 St 67  1732 
16  D3 St 55  1732 

実際にはError in df$Name : $ operator is invalid for atomic vectorsと表示されます。私の実際のデータと私のサンプルデータとの唯一の違いは、私の実際のデータのcount列がnumの代わりにintと表示されていることです。 count列のintの値を使用するには、この値が必要です。

私がAlカウントの合計を得た後、StとUnカウントの合計をそれぞれの列で得るプロセスを繰り返します。

EDIT:サンプルデータを展開し、私が作業しているデータフレームのリストについてもう少し詳しい情報を追加しました。

答えて

1

経由を使用することができます。 Name'A1'に等しい行については、(Name == 'Al') * countcountに等しく、そうでない行は0になります。 (代わりに、その式をifelse(Name == 'A1', count, 0)に置き換えることもできます)。 で合計するには、aveを使用します。注2の末尾にmydf0を使用しています。

与える
transform(mydf0, Al.sum = ave((Name == 'Al') * count, Location, FUN = sum)) 

Location Name count Al.sum 
1  D1 Al 6000 10980 
2  D1 Al 4980 10980 
3  D1 St 123 10980 
4  D1 St 98 10980 
5  D1 Un 87 10980 
6  D1 St 51 10980 
7  D2 Al 10989 19745 
8  D2 Al 8756 19745 
9  D2 St 457 19745 
10  D2 St 233 19745 

を例データが全くNA値を持っていたので、我々はsum(..., na.rm = TRUE)と気にしませんでしたが、これがためにあるNA値がある他のデータに拡張される場合削除した後、sumfunction(x) sum(x, na.rm = TRUE)に置き換えます。

リスト

質問は、複数のデータフレームを言及したが例を与えるものではありません。したがって、以下に示すデータフレームのリストLがあるとします。その後:

L <- list(mydf0, mydf0) 

lapply(L, transform, Al.sum = ave((Name == 'Al') * count, Location, FUN = sum)) 

注:私たちは、このような問題の解決策を修正することができます。 greplは、非Alカウントがゼロになるように、乗算するときに0/1ベクトルと見なされる論理ベクトルになります。次にbyはこれをLocationに適用し、rbindはピース(Locationに1つ)をまとめます。

add.al.sum = function(df) { 
    transform(df, Al.sum = sum(grepl("Al", Name) * count, na.rm = TRUE)) 
} 
do.call("rbind", by(mydf0, mydf$Location, add.al.sum)) 

注2:最初にデータフレームを修正:

mydf0 <- mydf # preserve mydf just in case 
mydf0[] <- lapply(mydf0, as.character) # make all cols character 
mydf0 <- transform(mydf0, count = as.numeric(count)) # make count numeric 
mydf0 <- subset(mydf0, Location != "") # remove blank lines 

がさらに簡単に、あなたは空白行を無視し、データを読み込むときことを保証することと列の文字を作るかもしれませんが、

+0

私は別のパッケージを必要としないというあなたのアプローチが好きです。私は私の例のデータに示していない1つの問題があると思います。私のデータには空白の行があります。したがって、mydf = transform(mydf、Al.sum = ave((Name == "Al")* count、Location、FUN = function(x)sum(x、na.rm = TRUE))) 'Iこのエラーメッセージが表示されます。(関数(...、row.names = NULL、check.rows = FALSE、check.names = TRUE、: の引数は行数が異なることを意味します:171,146,132,147,149 、148,138,143,114,111,115,101,112,218,122,96,156,128 '空行をスキップする方法を教えてください。 – aminards

+0

上記のエラーメッセージが関連していることがわかります私のリスト内の各データフレームの行数が異なっていることを確認するにはどうすればよいですか? – aminards

+0

質問を編集しました。 – aminards

2

私たちは、これは何のパッケージを使用しないと、コードの一行だけですdplyr

library(dplyr) 
mydf %>% 
    group_by(Location) %>% 
    mutate(Al.sum = sum(count[Name == 'Al'])) 

#Source: local data frame [10 x 4] 
#Groups: Location [2] 

# Location Name count Al.sum 
#  <fctr> <fctr> <dbl> <dbl> 
#1  D1  Al 6000 10980 
#2  D1  Al 4980 10980 
#3  D1  St 123 10980 
#4  D1  St 98 10980 
#5  D1  Un 87 10980 
#6  D1  St 51 10980 
#7  D2  Al 10989 19745 
#8  D2  Al 8756 19745 
#9  D2  St 457 19745 
#10  D2  St 233 19745 

またはdata.table

library(data.table) 
setDT(mydf)[, Al.sum := sum(count[Name == 'Al']), by = Location] 
+0

dplyrメソッドを試してみると、エラーメッセージUseMethod( "group_by_")のエラー: 'group_by_'の適用可能なメソッドがクラス "list"のオブジェクトに適用されていません。 。私はこれをデータフレームのリストに適用しようとしているからだと思います。 – aminards