web-dev-qa-db-ja.com

Rで文字型変換をNA強制なしの数値に変換する

私はRで作業していて、数値ベクトルを持つデータフレームdd_2006を持っています。最初にデータをインポートしたとき、SumOfCost、SumOfCases、SumOfUnitsの3つの変数から$、小数点、およびいくつかの空白を削除する必要がありました。そのために、私は_str_replace_all_を使用しました。ただし、_str_replace_all_を使用すると、ベクターは文字に変換されました。したがって、as.numeric(var)を使用してベクトルを数値に変換しましたが、as.numericコードを実行する前に以下のコードを実行した場合でも、NAが導入されましたが、ベクトルにはNAがありませんでした。

_sum(is.na(dd_2006$SumOfCost))
[1] 0
sum(is.na(dd_2006$SumOfCases))
[1] 0
sum(is.na(dd_2006$SumOfUnits))
[1] 0
_

これは、ベクトルから$を削除することから始まる、インポート後の私のコードです。 str(dd_2006)出力では、スペースを確保するために一部の変数を削除したため、以下の_str_replace_all_コードの列#は、ここに投稿した出力と一致しません(しかし彼らは元のコードで行います):

_library("stringr")
dd_2006$SumOfCost <- str_sub(dd_2006$SumOfCost, 2, ) #2=the first # after the $

#Removes decimal pt, zero's after, and commas
dd_2006[ ,9] <- str_replace_all(dd_2006[ ,9], ".00", "")
dd_2006[,9] <- str_replace_all(dd_2006[,9], ",", "")

dd_2006[ ,10] <- str_replace_all(dd_2006[ ,10], ".00", "")
dd_2006[ ,10] <- str_replace_all(dd_2006[,10], ",", "")

dd_2006[ ,11] <- str_replace_all(dd_2006[ ,11], ".00", "")
dd_2006[,11] <- str_replace_all(dd_2006[,11], ",", "")

str(dd_2006)
'data.frame':   12604 obs. of  14 variables:
 $ CMHSP                     : Factor w/ 46 levels "Allegan","AuSable Valley",..: 1 1 1
 $ FY                        : Factor w/ 1 level "2006": 1 1 1 1 1 1 1 1 1 1 ...
 $ Population                : Factor w/ 1 level "DD": 1 1 1 1 1 1 1 1 1 1 ...
 $ SumOfCases                : chr  "0" "1" "0" "0" ...
 $ SumOfUnits                : chr  "0" "365" "0" "0" ...
 $ SumOfCost                 : chr  "0" "96416" "0" "0" ...
_

次のコードを使用して、私と同様の質問 here への応答を見つけました。

_# create dummy data.frame
d <- data.frame(char = letters[1:5], 
                fake_char = as.character(1:5), 
                fac = factor(1:5), 
                char_fac = factor(letters[1:5]), 
                num = 1:5, stringsAsFactors = FALSE)
_

Data.frameを見てみましょう

_> d
  char fake_char fac char_fac num
1    a         1   1        a   1
2    b         2   2        b   2
3    c         3   3        c   3
4    d         4   4        d   4
5    e         5   5        e   5
_

そして実行してみましょう:

_> sapply(d, mode)
       char   fake_char         fac    char_fac         num 
"character" "character"   "numeric"   "numeric"   "numeric" 
> sapply(d, class)
       char   fake_char         fac    char_fac         num 
"character" "character"    "factor"    "factor"   "integer" 
_

おそらく、「異常はどこにあるのか」と自問するでしょう。さて、私はRで非常に奇妙なことに遭遇しましたが、これは最も混乱させるものではありませんが、特にベッドに入る前にこれを読んだ場合、混乱する可能性があります。

最初の2列は文字です。私は意図的に2nd one fake_charと呼んでいます。この文字変数と、ダークが返信で作成した文字変数の類似性を見つけます。実際には、文字に変換された数値ベクトルです。 3番目と4番目の列は因子であり、最後の列は「純粋に」数値です。

変換関数を利用する場合、fake_charを数値に変換できますが、char変数自体は変換できません。

_> transform(d, char = as.numeric(char))
  char fake_char fac char_fac num
1   NA         1   1        a   1
2   NA         2   2        b   2
3   NA         3   3        c   3
4   NA         4   4        d   4
5   NA         5   5        e   5
Warning message:
In eval(expr, envir, enclos) : NAs introduced by coercion
but if you do same thing on fake_char and char_fac, you'll be lucky, and get away with no NA's:
_

transform(d、fake_char = as.numeric(fake_char)、char_fac = as.numeric(char_fac))

_  char fake_char fac char_fac num
1    a         1   1        1   1
2    b         2   2        2   2
3    c         3   3        3   3
4    d         4   4        4   4
5    e         5   5        5   5
_

そのため、スクリプトで上記のコードを試しましたが、まだNAを考え出しました(強制に関する警告メッセージはありませんでした)。

_#changing sumofcases, cost, and units to numeric
dd_2006_1 <- transform(dd_2006, SumOfCases = as.numeric(SumOfCases), SumOfUnits = as.numeric(SumOfUnits), SumOfCost = as.numeric(SumOfCost))

> sum(is.na(dd_2006_1$SumOfCost))
[1] 12
> sum(is.na(dd_2006_1$SumOfCases))
[1] 7
> sum(is.na(dd_2006_1$SumOfUnits))
[1] 11
_

また、table(dd_2006$SumOfCases)などを使用して観測を調べ、観測で見逃した文字があるかどうかを確認しましたが、何もありませんでした。 NAがポップアップしている理由、およびそれらを取り除く方法についての考えはありますか?

7
idemanalyst

Anandoが指摘したように、問題はデータのどこかにあり、再現可能な例がなければ、私たちは実際にはあまり役に立ちません。つまり、問題の原因となっているデータのレコードを特定するのに役立つコードスニペットを次に示します。

test = as.character(c(1,2,3,4,'M'))
v = as.numeric(test) # NAs intorduced by coercion
ix.na = is.na(v)
which(ix.na) # row index of our problem = 5
test[ix.na]  # shows the problematic record, "M"

NAが導入されている理由を推測する代わりに、問題の原因となっているレコードを引き出して、NAがなくなるまで直接または個別にそれらに対処します。

更新:str_replace_allへの呼び出しに問題があるようです。 stringrライブラリはわかりませんが、gsubを使用して同じことを次のように実行できると思います。

v2 = c("1.00","2.00","3.00")
gsub("\\.00", "", v2)

[1] "1" "2" "3"

私はこれが何を達成するのか完全にはわかりません:

sum(as.numeric(v2)!=as.numeric(gsub("\\.00", "", v2))) # Illustrate that vectors are equivalent.

[1] 0

これが特定の目的を達成しない限り、このステップは前処理から完全に削除することをお勧めします。これは、必要とは思われず、問題を引き起こしているようです。

13
David Marx

文字も数値に変換したい場合は、まずそれを因子に変換し(as.factorを使用)、既存の変数を保存/上書きします。次に、この因子変数を数値に変換します(as.numericを使用)。この方法でNAを作成することはなく、所有しているデータセットを数値に変換できます。

4
phoenix31_adv

単純な解決策は、retypeに各列の新しいデータ型を推測させることです

library(dplyr)
library(hablar)

dd_2006 %>% retype()
0
davsjob