2017-05-23 3 views
1

오류 값을 포함하여 측정 된 값이 포함 된 일부 열이있는 csv 파일이 있습니다. numpy genfromtxt를 사용하여 파이썬으로 모든 것을 가져오고 dtype을 사용하여 배열을 포맷하려고합니다. 이 전 형식으로 csv 파일을 가정 해 봅시다 : 나는 열 강도의 두 서브 칼럼으로 전체 파일 및 분할 값과 불확실성을 분석 할numpy dtype 및 변환기를 사용하는 하위 열에서 csv 열 분할

# Name, Time, Intensity 
Sample1, 300, 1000+-5 
Sample2, 300, 1500+-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를 가져 오려고합니다. 출력은 다시 마지막으로

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

하지만, 수입 자체를 예상 부여합니다

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)) 

: [강도 열은 잘못된 형식을 가지고, 나는 올바른 형식으로 출력을 변환하는 컨버터를 사용하려면 오류가 발생합니다.

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가 다른 방식으로 데이터를 처리합니까? 나는 누군가가 생각하기를 바랍니다. 고마워.

+0

필드를 두 개로 나눠서 작동시키지 못하는 변환기를 테스트했습니다. 나는 그것이 불가능하다고 말하지 않을 것이지만, 그것은 컨버터의 의도 된 사용이 아니다. 하지만 왜 실패하는지, 그리고 퍼지가 있는지를보기 위해'genfromtxt'를 연구해야합니다. – hpaulj

+0

'TypeCSV'는 4 열 파일과 함께 작동합니까? – hpaulj

답변

1
당신의 DTYPE와

, 4 열, 그것은

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')])]) 

는 그래서 값의 단순 목록, 예를 취할 수 있습니다 (중첩 DTYPE 모두)를 작동 ['Sample1', 300, 1000, 5] 및 중첩 된 튜플에 매핑하여이 dtype을 저장해야합니다 ( ('Sample1', 300, (1000, 5))).

그러나 변환기가 ['Sample1', '300', '1000+-5']['Sample1', '300', (1000, 5)]으로 바꾸지 않거나 그렇지 않으면 이후 사용을 위해 올바르지 않습니다.오류 메시지에서

dtype_flat

입니다 : 그 효과에 코멘트 그냥 오류 줄 앞에있어 사실

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')])]) 

: 그래서 당신의 중첩 된 DTYPE이 같은 순서로 제작되어

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

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이 시점에서 이미 컨버터를 통과 한 row` 튜플 '의 SA 목록 : 그래서

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)] 

: 간단하게 변환 프로세스는

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] 

하지만 실제로 가까이

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

입니다

길고 짧다는 것은 converters이 열을 2 개 이상의 열로 나눌 수 없다는 것입니다. 분할, 변환 및 dtype에 매핑하는 프로세스가 잘못된 순서로 발생합니다. 내가 처음에 시연 한 것은 아마도 easist 일 것입니다. 텍스트 처리 라인을 통해 한 줄씩 파일을 전달하십시오. +-을 지정된 분리 문자로 바꿉니다. 그런 다음 파일의 dtype에 사용할 열의 수가 올 Y 르게됩니다.

관련 문제