2016-01-18 4 views
8

私は多くの列(〜50)を持つdata.frameを持っています。それらのうちのいくつかは文字であり、いくつかは数値であり、3つはグループ化に使用します。R:複数の列(数値、文字)を要約し、NAsを取り除く

私が行う必要があります。

  • は、文字列の最初の要素を抽出する数値列のそれぞれの平均値を計算する数値列からNASに削除

たとえば、以下のように変更された虹彩データを使用しています:

data(iris) 
iris$year <- rep(c(2000,3000),each=25) ## for grouping 
iris$color <- rep(c("red","green","blue"),each=50) ## character column 
iris[1,] <- NA ## introducing NAs 

合計で〜50列あり、数値と文字は混在しています。私は何を取得することは、それぞれのグループ内の最初の値を持つ列が続くグループ内のすべての列のための手段である

giris <- group_by(iris, Species, year) 
cls <- unlist(sapply(giris, class)) ## find out classes 
action <- ifelse(cls == "numeric", "mean", "first") 
action <- paste(action) 
summarise_each(giris, action) 

:私のような何かをしようとしてきました。そして、NAsは処理されない...正確には私が求めるものではない...

ヘルプ誰ですか?

答えて

9

あなたはsummarise_eachfunsif/elseでこれを試みることができる:

iris %>% 
    group_by(Species, year) %>% 
    summarise_each(funs(if(is.numeric(.)) mean(., na.rm = TRUE) else first(.))) 

あなたが列をグループ化するには、いくつかのNAのも持っているので、あなたがfilterステートメントを追加することができます。

iris %>% 
    filter(!is.na(Species) & !is.na(year)) %>% 
    group_by(Species, year) %>% 
    summarise_each(funs(if(is.numeric(.)) mean(., na.rm = TRUE) else first(.))) 
#Source: local data frame [6 x 7] 
#Groups: Species [?] 
# 
#  Species year Sepal.Length Sepal.Width Petal.Length Petal.Width color 
#  (fctr) (dbl)  (dbl)  (dbl)  (dbl)  (dbl) (chr) 
#1  setosa 2000  5.025 3.479167  1.4625  0.250 red 
#2  setosa 3000  4.984 3.376000  1.4640  0.244 red 
#3 versicolor 2000  6.012 2.776000  4.3120  1.344 green 
#4 versicolor 3000  5.860 2.764000  4.2080  1.308 green 
#5 virginica 2000  6.576 2.928000  5.6400  2.044 blue 
#6 virginica 3000  6.600 3.020000  5.4640  2.008 blue 

カラー列(または数値以外の列)で潜在的なNAを避けるには、first(na.omit(.))に変更できます。


またdata.tableを試みることができる:

library(data.table) 
setDT(iris) 
iris[!is.na(Species) & !is.na(year), lapply(.SD, function(x) { 
    if(is.numeric(x)) mean(x, na.rm = TRUE) else x[!is.na(x)][1L]}), 
    by = list(Species, year)] 
#  Species year Sepal.Length Sepal.Width Petal.Length Petal.Width color 
#1:  setosa 2000  5.025 3.479167  1.4625  0.250 red 
#2:  setosa 3000  4.984 3.376000  1.4640  0.244 red 
#3: versicolor 2000  6.012 2.776000  4.3120  1.344 green 
#4: versicolor 3000  5.860 2.764000  4.2080  1.308 green 
#5: virginica 2000  6.576 2.928000  5.6400  2.044 blue 
#6: virginica 3000  6.600 3.020000  5.4640  2.008 blue 
+0

'group_by'の上に' na.omit() 'を追加したいと思うかもしれませんが、これは質問の要点です。 – JasonAizkalns

+0

@JasonAizkalns、私はそうは思わない - これは潜在的に多くの行を削除する必要があります保持する必要があります。しかし、私は 'filter(!is.na(種)&!is.na(年))'が意味をなさないことに同意します –

+0

これは本当に素晴らしい(最も重要な)作業ソリューションであり、 summarise_eachのフードの下にある。私は本当に、本当に感謝しています、Doncendo :-)。同時に、それをスピードアップする方法があると思いますか? – rpl

0

私はそれを試してみてください:あなたが言及最初の点について

1. を、私は以下の(ISNのような何かをするだろう2番目のポイントに必要):

na.omit(iris[ , which(sapply(iris, class) == "numeric")]) 

iris[ , which(sapply(iris, class) == "numeric")] 
iris[ , which(sapply(iris, class) == "character")] 

2. 私はcolMeansで上記の行を組み合わせた2番目のタスク:

colMeans(iris[ , which(sapply(iris, class) == "numeric")], na.rm = TRUE) 

3列はnumericまたはcharacterいずれかBEI、私は次のように使用します。 は、あなたは、単に行うことができ、文字列の最初の要素を抽出するには:アイリスデータのために述べた場合

iris[1, which(sapply(iris, class) == "character")] 

、最初の行はcompletly NA、でも文字列があるので、私は見つけること繰り返すだろう最初の非NA-行

k <- 1 
while(any(is.na(FirstCharacterElement <- iris[k, which(sapply(iris, class) == "character")]))){ 
    k <- k + 1 
} 

は、列の種は、クラスファクターであり、あなたは多分それは文字であることを期待アイリスデータの場合には、コードを破るクラスファクタ(約注意してくださいこれを確認するにはsapply(iris, class)と入力してください。例:

iris$Species <- as.character(iris$Species) #or with similar column names 

データを読み込むときは、関数read.tableread.csvなどのパラメータstringsAsFactors = FALSEを挙げることができます。

関連する問題