2017-05-23 11 views
1

エラー値を含む測定値を含むいくつかの列を持つcsvファイルがあります。私はnumpy genfromtxtを使ってすべてをPythonにインポートし、dtypeを使って配列をフォーマットしたいと思います。のは、私がこの形式でCSVファイルを持っていると仮定しましょう:私はコラム強度の2つのサブ列にファイル全体と分割値と不確実性を解析したいnumpyのdtypeとコンバーターを使用したサブカラムの分割csv列

# Name, Time, Intensity 
Sample1, 300, 1000+-5 
Sample2, 300, 1500+-2 

。私は2つのdtypesに定義:このdtypesを使用して

import numpy as np 
TypeValErr = np.dtype([("value", np.int32), ("error", np.int32)]) 
TypeCSV=np.dtype({"names": ["name", "time", "intensity"], 
        "formats": ["U32", np.int32, TypeValErr], 
        "titles": ["Name", "Time", "Intensity"]}) 

を、私が最初に自分でちょうどテストアレイを作成します。次のステップでは、私に期待される出力

[('Sample3', 300, (2000, 12))] 

を与える

Intensity = np.array([(2000, 12)], dtype=TypeValErr) 
CSVentry = np.array([("Sample3", 300, Intensity)], dtype=TypeCSV) 

print(CSVentry) 

をこのdtypeを使用してCSVをインポートします。強度列が間違った形式を持っているように、私は適切なフォーマットに出力を変換するコンバータを使用する:

def convertToValErrArr(txt): 
    splitted = txt.split("+-") 
    return np.array([(splitted[0], splitted[1])], dtype=TypeValErr) 

print(np.array([("Sample3", 300, convertToValErrArr("1800+-7"))], dtype=TypeCSV)) 

出力が再び期待

[('Sample3', 300, (1800, 7))] 

しかし、最終的には、輸入自体を与えますエラーを投げます。

ConvertFunc = lambda x: convertToValErrArr(x) 

file = np.genfromtxt("test.csv", 
        delimiter=",", 
        autostrip=True, 
        dtype=TypeCSV, 
        skip_header=1, 
        converters={2: lambda x: convertToValErrArr(str(x))}) 

そして、ここに私のエラーです:

Traceback (most recent call last): 
    File "csvimport.py", line 28, in <module> 
    converters={2: lambda x: convertToValErrArr(str(x))}) 
    File "/usr/lib/python3.6/site-packages/numpy/lib/npyio.py", line 1896, in genfromtxt 
    rows = np.array(data, dtype=[('', _) for _ in dtype_flat]) 
ValueError: size of tuple must match number of fields. 

私は間違いを見ていないが、ここに私のコードです。 genfromtxtは別の方法でデータを処理していますか?私は誰かがアイデアを持っていることを願っていますどうもありがとう。あなたのDTYPEで

+0

フィールドを2つに分割して動作させることができないコンバータをテストしました。私はそれが不可能だとは言わないが、それはコンバータの意図された使用ではない。しかし、なぜそれが失敗するのか、何かファッジがあるのか​​を知るためには、genfromtxtを調べなければなりません。 – hpaulj

+0

'TypeCSV'は4列のファイルで動作しますか? – hpaulj

答えて

1

、4列、それは(ネストされたDTYPEとすべてを)作品

In [58]: TypeValErr = np.dtype([("value", np.int32), ("error", np.int32)]) 
    ...: TypeCSV=np.dtype({"names": ["name", "time", "intensity"], 
    ...:     "formats": ["U32", np.int32, TypeValErr], 
    ...:     "titles": ["Name", "Time", "Intensity"]}) 
    ...: 
In [59]: txt=b"""# Name, Time, Intensity 
    ...: Sample1, 300, 1000, 5 
    ...: Sample2, 300, 1500, 2""" 
In [60]: 
In [60]: data=np.genfromtxt(txt.splitlines(), dtype=TypeCSV, delimiter=',',skip_header=True) 
In [61]: data 
Out[61]: 
array([('Sample1', 300, (1000, 5)), ('Sample2', 300, (1500, 2))], 
     dtype=[(('Name', 'name'), '<U32'), (('Time', 'time'), '<i4'), (('Intensity', 'intensity'), [('value', '<i4'), ('error', '<i4')])]) 

だから、例えば、値のフラットリストを取ることができるです['Sample1', 300, 1000, 5]とネストされたタプルにマップすると、このdtypeを保存する必要があります。 ('Sample1', 300, (1000, 5))

しかし、変換器で['Sample1', '300', '1000+-5']['Sample1', '300', (1000, 5)]に変換されないか、またはそれ以降の使用に適切なものではありません。エラーメッセージの

dtype_flat次のとおりです。

In [70]: np.lib.npyio.flatten_dtype(TypeCSV) 
Out[70]: [dtype('<U32'), dtype('int32'), dtype('int32'), dtype('int32')] 

だからあなたのネストされたDTYPEは、このような順序で生産されています。実際には

In [75]: rows=np.array(('str',1,2, 3),dtype=[('',_) for _ in np.lib.npyio.flatten_dtype(TypeCSV)]) 
In [76]: rows.view(TypeCSV) 
Out[76]: 
array(('str', 1, (2, 3)), 
     dtype=[(('Name', 'name'), '<U32'), (('Time', 'time'), '<i4'), (('Intensity', 'intensity'), [('value', '<i4'), ('error', '<i4')])]) 

だけでエラー行の前にその旨のコメントがあります

if len(dtype_flat) > 1: 
     # Nested dtype, eg [('a', int), ('b', [('b0', int), ('b1', 'f4')])] 
     # First, create the array using a flattened dtype: 
     # [('a', int), ('b1', int), ('b2', float)] 
     # Then, view the array using the specified dtype. 
     if 'O' in (_.char for _ in dtype_flat): 
     ... 
     else: 
      rows = np.array(data, dtype=[('', _) for _ in dtype_flat]) 
      output = rows.view(dtype) 

dataこの時点でだから、

In [87]: rows = [row,row] 
In [88]: rows 
Out[88]: [['one', '1', '2', '3'], ['one', '1', '2', '3']] 
In [89]: from operator import itemgetter 
In [90]: [[conv(r) for r in map(itemgetter(i), rows)] for (i, conv) in enumerate(converters)] 
Out[90]: [['one', 'one'], [1, 1], [2, 2], [3, 3]] 
In [91]: list(zip(*_)) 
Out[91]: [('one', 1, 2, 3), ('one', 1, 2, 3)] 

rows = list(
     zip(*[[conv._strict_call(_r) for _r in map(itemgetter(i), rows)] 
       for (i, conv) in enumerate(converters)])) 

は、変換プロセスが

In [84]: converters = [str, int, int, int] 
In [85]: row = ['one','1','2','3'] 
In [86]: [conv(r) for conv, r in zip(converters, row)] 
Out[86]: ['one', 1, 2, 3] 

が、実際に近い簡素化:すでにコンバーターを通過してきた「row`タプルのSAリスト長短はconvertersは2つ以上の列に列を分割できないということです。分割、変換、そしてdtypeへのマッピングのプロセスは、このために間違った順序で行われます。私が最初に実証したのはおそらく簡単です - ファイルを1行ずつテキスト処理ラインで渡します。 +-の代わりに、指定された区切り文字が使用されます。次に、dtypeで動作する正しい数の列がファイルに格納されます。

関連する問題