桁区切り記号としてカンマが含まれている数値がある場合にデータを読み取る方法は?


117

私は数値の一部は、例えば桁区切りとしてカンマで文字列として表現されているCSVファイル持っている"1,513"代わりにします1513。データをRに読み込む最も簡単な方法は何ですか?

私はを使用できますがread.csv(..., colClasses="character")、それらの列を数値に変換する前に、関連する要素からコンマを取り除く必要があり、そのためのきちんとした方法を見つけることができません。

回答:


141

わからないどのくらい持っているread.csvそれを正しく解釈していますが、使用することができますgsub置き換えること","""、その後に文字列を変換するnumeric使用してas.numeric

y <- c("1,200","20,000","100","12,111")
as.numeric(gsub(",", "", y))
# [1]  1200 20000 100 12111

これは以前にR-Helpでも回答されましたここではQ2でも)。

あるいは、たとえばsedunixでファイルを前処理することもできます。


60

read.tableまたはread.csvでこの変換を半自動的に行うことができます。最初に新しいクラス定義を作成し、次に変換関数を作成し、次のようにsetAs関数を使用して「as」メソッドとして設定します。

setClass("num.with.commas")
setAs("character", "num.with.commas", 
        function(from) as.numeric(gsub(",", "", from) ) )

次に、read.csvを次のように実行します。

DF <- read.csv('your.file.here', 
   colClasses=c('num.with.commas','factor','character','numeric','num.with.commas'))

3
これはとてもいいトリックです。インポート時の変換(たとえば、を使用してY / N値を論理ベクトルに変換する)に使用できますsetAs("character", "logical.Y.N", function(from) c(Y=TRUE,N=FALSE)[from] )
Marek、

1
同様の問題で同じトリックを使用します。追加すると、いずれsetClass("num.with.commas")suppresMessage(setAs(.....))を使用するか、欠落しているクラスに関するメッセージを回避できます。
Marek、

こんにちはグレッグ、この便利な機能を共有してくれてありがとう。実行すると、次の警告が表示されます。「coerce」のシグネチャ「 "character"、 "num.with.commas"」のメソッド:クラス「num.with.commas」の定義がありません。私はあなたのコードを一語一句持っていますか?
TheGoat 2016

私は同様の問題のリンクを調べたところ、クラスを設定する必要があることがわかりました!きちんとしたトリックをありがとう。
TheGoat 2016

17

データを前処理するよりもRを使用したいと思います。データを修正するときに簡単になるからです。シェーンのを使用するという提案に従ってgsub、これは私ができる限りきれいだと思います:

x <- read.csv("file.csv",header=TRUE,colClasses="character")
col2cvt <- 15:41
x[,col2cvt] <- lapply(x[,col2cvt],function(x){as.numeric(gsub(",", "", x))})

colClasses = "char"はすべての列を強制的にcharにしませんか?その場合、15:41以外の他の列もcharになりますか?たぶん、read.csv()に決定させ、それをcols 15:41で変換すると、「より多くの」数値列が得られるかもしれません。
Dirk Eddelbuettel、2009年

はい、しかし私の質問が述べたように、他のすべての列は個性的です。代わりに、もっと一般的なas.is = TRUEを使用できます。しかし、デフォルトの引数を使用してread.csv()に決定させることは、文字のように見えるものはすべて数値列に面倒を引き起こす要因に変換するため、as.numeric()を使用して適切に変換されないため、役に立ちません。 。
Rob Hyndman、

読み取りテーブルのdec =引数を "。"に設定することを検討する必要があります。これがread.csv2のデフォルトですが、カンマはread.csv()に組み込まれています。
IRTFM、2011年

15

この質問は数年前のものですが、私はそれを偶然見つけました。

readrライブラリ/パッケージはそれにいくつかの素晴らしい機能を備えています。それらの1つは、このように「乱雑な」列を解釈するための良い方法です。

library(readr)
read_csv("numbers\n800\n\"1,800\"\n\"3500\"\n6.5",
          col_types = list(col_numeric())
        )

これは

ソース:ローカルデータフレーム[4 x 1]

  numbers
    (dbl)
1   800.0
2  1800.0
3  3500.0
4     6.5

ファイルを読み取る際の重要なポイント:上記のに関するコメントのように前処理するか、読み取り中sedに処理する必要があります。多くの場合、事後に問題を修正しようとすると、見つけるのが難しい危険な仮定がいくつかあります。(これが、フラットファイルがそもそも邪悪な理由です。)

たとえばcol_types、にフラグを付けていなかったとしたら、次のようになります。

> read_csv("numbers\n800\n\"1,800\"\n\"3500\"\n6.5")
Source: local data frame [4 x 1]

  numbers
    (chr)
1     800
2   1,800
3    3500
4     6.5

(今ではなくchrcharacter)になっていることに注意してくださいnumeric。)

または、さらに危険なのは、それが十分に長く、初期の要素のほとんどにコンマが含まれていない場合です。

> set.seed(1)
> tmp <- as.character(sample(c(1:10), 100, replace=TRUE))
> tmp <- c(tmp, "1,003")
> tmp <- paste(tmp, collapse="\"\n\"")

(最後のいくつかの要素は次のようになります:)

\"5\"\n\"9\"\n\"7\"\n\"1,003"

次に、そのコンマをまったく読むのが難しいでしょう。

> tail(read_csv(tmp))
Source: local data frame [6 x 1]

     3"
  (dbl)
1 8.000
2 5.000
3 5.000
4 9.000
5 7.000
6 1.003
Warning message:
1 problems parsing literal data. See problems(...) for more details. 

7

とパイプdplyrを使用mutate_allしたソリューション

あなたが次のものを持っていると言います:

> dft
Source: local data frame [11 x 5]

   Bureau.Name Account.Code   X2014   X2015   X2016
1       Senate          110 158,000 211,000 186,000
2       Senate          115       0       0       0
3       Senate          123  15,000  71,000  21,000
4       Senate          126   6,000  14,000   8,000
5       Senate          127 110,000 234,000 134,000
6       Senate          128 120,000 159,000 134,000
7       Senate          129       0       0       0
8       Senate          130 368,000 465,000 441,000
9       Senate          132       0       0       0
10      Senate          140       0       0       0
11      Senate          140       0       0       0

また、年の変数X2014-X2016からコンマを削除し、数値に変換したいとします。また、X2014-X2016が因子として読み込まれるとしましょう(デフォルト)

dft %>%
    mutate_all(funs(as.character(.)), X2014:X2016) %>%
    mutate_all(funs(gsub(",", "", .)), X2014:X2016) %>%
    mutate_all(funs(as.numeric(.)), X2014:X2016)

mutate_all内部の関数をfuns指定された列に適用します

一度に1つの関数を順番に実行しました(内部で複数の関数を使用する場合はfuns、追加の不要な列を作成します)


3
mutate_each廃止予定です。回答をmutate_at類似のものに更新しますか?
T_T 2018

6

Rの「前処理」:

lines <- "www, rrr, 1,234, ttt \n rrr,zzz, 1,234,567,987, rrr"

使用することができreadLines、Aの上にtextConnection。次に、数字の間にあるコンマのみを削除します。

gsub("([0-9]+)\\,([0-9])", "\\1\\2", lines)

## [1] "www, rrr, 1234, ttt \n rrr,zzz, 1234567987, rrr"

知っておくと便利ですが、小数点としてのカンマはread.csv2(自動)またはread.table(「dec」パラメータの設定あり)で処理できることは、この質問には直接関係ありません。

編集:後で、新しいクラスを設計してcolClassesを使用する方法を発見しました。見る:

数値クラスとしてRに1000セパレータ付きのdfをロードする方法は?


おかげで、これは良いポインタでしたが、1,234,567.89など、いくつかの小数点を含む数字では機能しません。GoogleスプレッドシートをRにインポートするには、この問題を回避する必要があります。簡単なものについては、stackoverflow.com / a / 30020171/3096626を参照してください複数の小数点の処理を行う関数
フレクシブ

4

番号が「。」で区切られている場合 呼び出し中によると小数「」(1.200.000,00)gsubあなたがしなければなりませんset fixed=TRUE as.numeric(gsub(".","",y,fixed=TRUE))


3

非常に便利な方法はreadr::read_delim-familyです。ここから例を挙げ ましょう。複数のセパレータを含むcsvをRにインポートするには、次のようにします。

txt <- 'OBJECTID,District_N,ZONE_CODE,COUNT,AREA,SUM
1,Bagamoyo,1,"136,227","8,514,187,500.000000000000000","352,678.813105723350000"
2,Bariadi,2,"88,350","5,521,875,000.000000000000000","526,307.288878142830000"
3,Chunya,3,"483,059","30,191,187,500.000000000000000","352,444.699742995200000"'

require(readr)
read_csv(txt) # = read_delim(txt, delim = ",")

どちらが期待される結果になります:

# A tibble: 3 × 6
  OBJECTID District_N ZONE_CODE  COUNT        AREA      SUM
     <int>      <chr>     <int>  <dbl>       <dbl>    <dbl>
1        1   Bagamoyo         1 136227  8514187500 352678.8
2        2    Bariadi         2  88350  5521875000 526307.3
3        3     Chunya         3 483059 30191187500 352444.7

3

readrライブラリの一部であるread_delim関数を使用して、追加のパラメーターを指定できます。

locale = locale(decimal_mark = ",")

read_delim("filetoread.csv", ';", locale = locale(decimal_mark = ","))

* 2行目のセミコロンは、read_delimがcsvセミコロンで区切られた値を読み取ることを意味します。

これにより、すべての数値をカンマで適切な数値として読み取ることができます。

よろしく

マテウス・カニア


3

も使用できますreadr::parse_numberが、列は文字でなければなりません。複数の列に適用する場合は、次のコマンドを使用して列をループできます。lapply

df[2:3] <- lapply(df[2:3], readr::parse_number)
df

#  a        b        c
#1 a    12234       12
#2 b      123  1234123
#3 c     1234     1234
#4 d 13456234    15342
#5 e    12312 12334512

または、mutate_atfrom dplyrを使用して特定の変数に適用します。

library(dplyr)
df %>% mutate_at(2:3, readr::parse_number)
#Or
df %>% mutate_at(vars(b:c), readr::parse_number)

データ

df <- data.frame(a = letters[1:5], 
                 b = c("12,234", "123", "1,234", "13,456,234", "123,12"),
                 c = c("12", "1,234,123","1234", "15,342", "123,345,12"), 
                 stringsAsFactors = FALSE)

1

前処理は進むべき道だと思います。正規表現の置換オプションがあるNotepad ++を使用できます。

たとえば、ファイルが次のような場合:

"1,234","123","1,234"
"234","123","1,234"
123,456,789

次に、正規表現"([0-9]+),([0-9]+)"を使用してそれを次のように置き換えることができます\1\2

1234,"123",1234
"234","123",1234
123,456,789

次にx <- read.csv(file="x.csv",header=FALSE)、ファイルを読み取るために使用でき ます。


22
スクリプトを作成できるものなら何でもいいです。手作業で行うと、エラーが発生する可能性があり、再現性も低くなります。
ハドリー2009年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.