5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

read.tableやread.csvで読み込まれるdataframeの列数は最初の5行で決まるらしい

Last updated at Posted at 2015-12-07

概要 - 列数はどうやって決まっているのか

先日研究室でR言語を使っていて、3列のデータを持つCSVからread.csv関数でdataframeを作ろうとしたところなぜか2列のデータとして認識されてしまう事案が発生しました。
このCSVの3列目は一部のレコードで存在し、それ以外の行はデータが入っていない(読み込むとNAになる)というものです。
例えばこんな感じで、col3にはデータが入っている行といない行があります

test.csv
col1,col2,col3
lorem,10
ipsum,18
dolor,30,true
sit,40
amet,23,false

read.csv("./test.csv", sep=",", header=F)を実行した結果

col1 col2 col3
lorem 10 NA
ipsum 18 NA
dolor 30 true
sit 40 NA
amet 23 false

ちなみに上記の例ではきちんと3列のデータとして読み込まれました。

また上記と同様のCSVを複数持っていたのですが、あるCSVでは3列で認識され、あるCSVは2列で認識されるという現象が起きたため「そもそもRのdataframeってどうやって行数判断されてるんだ??」という疑問が生まれたのでした。

結論 - 最初の5行が判断材料

read.csv(read.tableでも同様)の公式リファレンスでは以下のような説明がされています。

The number of data columns is determined by looking at the first five lines of input (or the whole input if it has less than five lines), or from the length of col.names if it is specified and is longer. This could conceivably be wrong if fill or blank.lines.skip are true, so specify col.names if necessary (as in the ‘Examples’).

翻訳すると
『列数は入力データの最初の5行(全体が5行未満ならば全ての行)を見て決定される。 もしくは**col.names が指定されており、かつそれが最初の5行で決められた列数よりも長ければ、そのcol.namesの長さから決定される。**ただし fill または blank.lines.skip オプションにTRUEが指定された場合はこの限りではないかもしれない。』
となります。

したがって要約すると

  • col.namesが指定されていない」 OR 「5行未満」 : 「5行目までの列数」 = 「dataframe全体の列数」
  • col.namesが指定されている」 AND 「5行以上」 : length(col.names)行目までの列数」 = 「dataframe全体の列数」

になるそうです。
うーんこれは知らなかった。
つまり冒頭の現象は、あるCSVでは最初に3列目が現れるのが6行目以降だったので2列と判定され、別のCSVでは5行目までに3列目のデータが現れていたため3列と認識されていたようでした。

3列として認識される例

3列のデータとして認識される例
col1,col2,col3
lorem,10
ipsum,18
dolor,30,true
sit,40
amet,23,true
consectetur,7,NA

read.tableした結果

col1 col2 col3
lorem 10 NA
ipsum 18 NA
dolor 30 true
sit 40 NA
amet 23 true
consectetur 7 NA

2列のデータとして認識される例 (5行目までに3列目が現れない)

2列と認識されてしまう例
lorem,10
ipsum,18
dolor,30
sit,40
amet,23
consectetur,7,true << 6行目以降のため無視される

read.tableした結果

col1 col2
lorem 10
ipsum 18
dolor 30
sit 40
amet 23
consectetur 7

ここでもし**col.namesc("col1", "col2", "col3")を指定すれば3列のデータとして認識されます**。

一部データが空の列への対処法 - カンマをつけるか列名をベクトルで指定する

また引用したリファレンスにもあったように、一部のデータ(特に最終列)が欠けたデータで正しく列数を認識させる方法は2つあると思います。

  1. 最終列が存在しない行では最後にカンマを入れる
  2. col.namesを(列名をベクトルで)指定する

前者の方法を用いる場合はデータ生成元でログの吐き出し方を変えるなどの対処が必要でしょう。
そのため既存の実装を変更する必要があります。
一方後者の方法はある種の列数指定ですので、冒頭に示したような最後にカンマのないデータに対しても列数を強制的に指定できるという点で有利ですが、col.namesの長さ分の行までしか検出されないのでかなり後方のデータになって初めて現れる場合は前者の方法を使うしかありません。

参考

5
2
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?