9

次のような形式の CSV ファイルがあります。

"FieldName1"、"FieldName2"、"FieldName3"、"FieldName4"
"2010 年 4 月 13 日 14:45:07.008"、"7.59484916392"、"10"、"6.552373"
"2010 年 4 月 13 日 14:45:22.010 "、"6.55478493312"、"9"、"3.5378543"
...

CSV ファイルの各行の先頭と末尾には二重引用符があり、","文字列は各行内のフィールドを区切るために使用されることに注意してください。CSV ファイルのフィールド数は、ファイルごとに異なります。

これを numpy 経由で読み込もうとすると、
import numpy as np
data = np.genfromtxt(csvfile, dtype=None, delimiter=',', names=True)
すべてのデータが二重引用符で囲まれた文字列値として読み込まれます。不合理ではありませんが、戻ってすべての列を正しい型に変換する必要があるため、あまり役に立ちません

代わりに使用すると、最初と最後のフィールドを除いdelimiter='","'て、すべてが思いどおりに機能します。行頭文字と行末文字は単一の二重引用符文字であるため、これは最初と最後のフィールドの有効な区切り文字とは見なされないため、たとえばandとして読み込まれます- 先頭と末尾の二重引用符に注意してください-文字をそれぞれ引用します。これらの冗長な文字のため、numpy は最初と最後のフィールドが両方とも String 型であると想定します。そうなってほしくない"04/13/2010 14:45:07.0086.552373"

最初の読み取り後にnumpy配列の構造に戻って「修正」することなく、この方法でフォーマットされたファイルを読み取るようにnumpyに指示する方法はありますか?

4

1 に答える 1

12

基本的な問題は、NumPy が引用符を取り除くという概念を理解していないことです (csvモジュールは理解しています)。と言うときdelimiter='","'、列区切り文字が文字通り引用符で囲まれたコンマであることを NumPy に伝えていることになります。

converters関数のドキュメントを見ると、パラメータを設定して引用符を削除する必要があると思います(デフォルトではそうではありません):

import re
import numpy as np

fieldFilter = re.compile(r'^"?([^"]*)"?$')
def filterTheField(s):
    m = fieldFilter.match(s.strip())
    if m:
        return float(m.group(1))
    else:
        return 0.0 # or whatever default

#...

# Yes, sorry, you have to know the number of columns, since the NumPy docs
# don't say you can specify a default converter for all columns.
convs = dict((col, filterTheField) for col in range(numColumns))
data = np.genfromtxt(csvfile, dtype=None, delimiter=',', names=True, 
    converters=convs)

または、放棄np.genfromtxt()csv.csvreaderて、ファイルの内容を文字列のリストとして一度に 1 行ずつ提供してから、要素を反復処理してマトリックスを作成します。

reader = csv.csvreader(csvfile)
result = np.array([[float(col) for col in row] for row in reader])
# BTW, column headings are in reader.fieldnames at this point.

編集:さて、ファイルがすべてフロートではないようです。convsその場合、必要に応じて設定genfromtxtするか、変換関数のベクトルを作成できますcsv.csvreader

reader = csv.csvreader(csvfile)
converters = [datetime, float, int, float]
result = np.array([[conv(col) for col, conv in zip(row, converters)] 
    for row in reader])
# BTW, column headings are in reader.fieldnames at this point.

編集 2: わかりました、可変列数... データ ソースは単に生活を困難にしたいだけです。幸いなことに、使用できるのはmagic...

reader = csv.csvreader(csvfile)
result = np.array([[magic(col) for col in row] for row in reader])

... wheremagic()は関数のために頭の中で思いついた名前です。(サイケ!)

最悪の場合、次のようになります。

def magic(s):
    if '/' in s:
        return datetime(s)
    elif '.' in s:
        return float(s)
    else:
        return int(s)

NumPy には、文字列を受け取り、正しい型の単一の要素を返す関数があるかもしれません。 numpy.fromstring()近いように見えますが、タイムスタンプのスペースを列区切りとして解釈する場合があります。

PS 1つの欠点csvreaderは、コメントを破棄しないことです。実際のcsvファイルにはコメントがありません。

于 2010-04-19T02:17:43.220 に答える