web-dev-qa-db-ja.com

データフレームの各列に既存のデータ型の各列を監視する関数を適用します

私は、私のデータを知るためにの一部として、大きなデータフレームの各列の最小/最大を取得しようとしています。私の最初の試みは:

apply(t,2,max,na.rm=1)

最初のいくつかの列は文字型であるため、すべてを文字ベクトルとして扱います。そのため、いくつかの数値列の最大値は" -99.5"

私はこれを試しました:

sapply(t,max,na.rm=1)

しかし、それはmaxが因子にとって意味がないと文句を言います。 (lapplyは同じです。)私を混乱させているのは、applymaxが因子にとって完全に意味があると思ったことです。列1に対して「ZEBRA」を返しました。

ところで、私は POSIXctのベクトルでsapplyを使用 を見て、答えの1つは「sapplyを使用すると、オブジェクトは数値に強制されます。」 。)」。これは私に起こっていることですか?もしそうなら、強制しない代替適用機能はありますか?データフレームタイプの重要な特徴の1つは、各列を異なるタイプにできることです。

49
Darren Cook

それが「順序付けられた要素」である場合、状況は異なります。 「順序付けられた因子」が好きだと言うのではなく、「因子」に対して定義されていない「順序付けられた因子」に対していくつかの関係が定義されていると言うだけではありません。因子は通常のカテゴリー変数と考えられています。ロケールのアルファベット順の字句順である因子の自然なソート順が表示されています。すべての列に対して「数値」への自動強制を取得したい場合は、...日付と要因、およびすべてを試してください:

sapply(df, function(x) max(as.numeric(x)) )   # not generally a useful result

または、最初に要因をテストし、期待どおりに戻りたい場合:

sapply( df, function(x) if("factor" %in% class(x) ) { 
            max(as.numeric(as.character(x)))
            } else { max(x) } )

@Darrensのコメントはより良く機能します:

 sapply(df, function(x) max(as.character(x)) )  

maxは文字ベクトルで成功します。

35
42-

maxapplyと連携する理由は、applyが最初にデータフレームをマトリックスに強制し、マトリックスが1つのデータ型しか保持できないためです。したがって、文字のマトリックスになります。 sapplylapplyの単なるラッパーなので、両方が同じエラーを生成することは驚くことではありません。

データフレームを作成するときのデフォルトの動作では、カテゴリー列はfactorsとして保存されます。 orderedファクターであると指定しない限り、Rはを作成したと仮定しているため、maxminなどの演算は未定義になります。順序なしファクター。

セッション全体のデフォルトを変更するoptions(stringsAsFactors = FALSE)を指定してこの動作を変更するか、data.frame()構築呼び出し自体にstringsAsFactors = FALSEを渡すことができます。これは、minおよびmaxがデフォルトで「アルファベット順」の順序を想定することを意味することに注意してください。

または、各要素の順序を手動で指定することもできますが、それがあなたのやりたいことだとは思いません。

とにかく、sapplyは一般にアトミックベクトルを生成し、多くの場合、すべてを文字に変換する必要があります。これを回避する1つの方法は次のとおりです。

#Some test data
d <- data.frame(v1 = runif(10), v2 = letters[1:10], 
                v3 = rnorm(10), v4 = LETTERS[1:10],stringsAsFactors = TRUE)

d[4,] <- NA

#Similar function to DWin's answer          
fun <- function(x){
    if(is.numeric(x)){max(x,na.rm = 1)}
    else{max(as.character(x),na.rm=1)}
}   

#Use colwise from plyr package
colwise(fun)(d)
         v1 v2       v3 v4
1 0.8478983  j 1.999435  J
17
joran

データを学習する場合は、summary (df)は、数値列の最小、1分位、中央値と平均、3分位と最大、および因子列の最上位レベルの頻度を提供します。

7
Itamar

@ltamarの答えに基づいて:
サマリーを使用して、出力を有用なものに変更します。

library(tidyr)
library(dplyr)

df %>% 
  summary %>% 
  data.frame %>%
  select(-Var1) %>%
  separate(data=.,col=Freq,into = c('metric','value'),sep = ':') %>%
  rename(column_name=Var2) %>%
  mutate(value=as.numeric(value),
         metric = trimws(metric,'both') 
  ) %>%  
  filter(!is.na(value)) -> metrics

それはきれいではなく、確かに高速ではありませんが、仕事は完了します!

2
hibernado

retype()を使用して、実現可能性に応じて文字または数値タイプにファクターを強制するhablarからのソリューション。各列にmaxを適用するためにdplyrを使用します。

コード

library(dplyr)
library(hablar)

# Retype() simplifies each columns type, e.g. always removes factors
d <- d %>% retype()

# Check max for each column
d %>% summarise_all(max)

結果

新しい列タイプではありません。

     v1 v2       v3 v4   
  <dbl> <chr> <dbl> <chr>
1 0.974 j      1.09 J   

データ

# Sample data borrowed from @joran
d <- data.frame(v1 = runif(10), v2 = letters[1:10], 
                v3 = rnorm(10), v4 = LETTERS[1:10],stringsAsFactors = TRUE)
0
davsjob

これを行うための絶対的な最良の方法は、データフレーム全体を配列に強制するbase * apply関数を避け、 colwise fromplyr。 (誰もこれに言及していないことに驚いています)

parse_guessをあらゆる種類のベクトルデータ型で動作する関数として使用する例:

colwise(parse_guess)(t)

あまりおもしろくない答え:forループを使用して各列に適用できます。

for (i in 1:nrow(t)) { t[, i] <- parse_guess(t[, i]) }

データフレーム構造を保持しながら* applyで割り当てを行う の良い方法がわかりません。

0
qwr