2013-05-08 3 views
1

다음 형식의 탭 구분 파일이 주어지면 열 단위로 작업을 수행해야합니다. 내가 아는 가장 쉬운 해결책은 팬더 패키지를 사용하는 것입니다. 그러나 제 파일은 몇 가지 공연이되고, 나는 그것을 읽는데 어려움을 겪고 있습니다. 그래서 나는 정상적인 스트리밍 방법을 사용하기로 결정했다.tabdelimited 파일의 열을 변수로 변환

여기서 동적으로 열 변수를 생성하고 싶습니다 (열 수는 ~ 500 개입니다). 각 열은 공백을 포함하여 특정 열의 모든 값을 저장합니다. 예 : 변수 a[11,22,31,,42,555]입니다.

a b c d e f 
11  9 9 1 6 
22 8 0 8 2 
31 7  7 3 5 
    6 1 6  4 
42 6 2 5 2 3 
555  3 4 1 2 

전체 파일을 한 번만 읽음으로써 어떻게 이러한 변수를 생성 할 수 있습니까?

with open('myfile.txt', 'r') as infile: 
    header = infile.readline() 
    col_values = {var:[] for var in header.split()} 
    var_idx_dict = {idx:var for idx,var in enumerate(header.split())} 

    for line in infile: 
     values = line.split('\t') 

     for idx,value in enumerate(values): 
      var = var_idx_dict[idx] 
      col_values [var].append(value) 

col_values 그 열의 모든 값의 목록에 각 키 가리키는, 당신의 열 헤더의 문자열 키를 포함해야합니다 :

+2

만약 그것이 부부 공연이라면 그냥 팬더를 사용하십시오. 더 많은 시간을 들이지 않고서는 훨씬 더 빠를 방법이 없습니다. pandas를 사용하여 열에 대한 색인을 생성하고 DataFrame을 조 변경하면 –

+0

전체 파일을 메모리에로드 할 수없고로드하는 것처럼 보입니다. 나는 판다의 최신 버전이있다. – learner

+0

팬더 0.11을 사용하고 최근에 저장된 파일에 각각 1 ~ 4GB의 데이터 프레임 10 개를로드했습니다. 약 30 분이 걸렸지 만 피클을 사용하여 내 컴퓨터에 저장했습니다. 내가 말하고있는 것은, 30 분을 기다리는 것은 그만한 가치가 있습니다. 다른 방법에서는 20 줄이 걸리며 여전히 상당한 시간이 걸릴 것이기 때문에 실제로는 '팬더'에 그냥 내장되어 있습니다. –

답변

0

는 목록의 사전을보십시오.

EDIT : 파일 크기가 매우 커서 자신의 환경을 잘 모르는 상태에서 팬더에 문제가있는 경우 PyTables를 사용해보십시오. 나는 그것에 대한 약간의 도움을 줄 수있다. 그것은 당신의 최종 목표 (기초 수학? 통계? 데이터 포맷?)에 달려있다.

import csv 

def get_column(name): 
    with open('filename', 'r') as handle: 
     reader = csv.DictReader(handle, delimiter='\t') 

     for row in reader: 
      yield row[name] 

을하지만 팬더 아마 빨리 당신이 데이터와 일을 시작하면 될 것입니다 :

+2

'col_values'는 * huge * 사전이 될 것입니다. – Blender

+0

정확히 !! 이것은 질문에 대답하지만, 솔직히 판다는 이와 같은 물건을 다루기 위해 만들어졌고 조금 더 시간이 걸릴지라도 가치가있을 것입니다 –

+0

판다에서 2GB가 소요된다면 dict에서 8GB와 같은 것. 모든 것을 반복하는 데 걸리는 시간은 말할 것도 없습니다. – abarnert

0

당신은 csv 모듈과 발전기로 읽을 수 있습니다.

+0

그래, 그는 할 수 있지만 문제의 어려운 부분을 해결하지는 못한다. 분명한 것은 목록을 작성하거나리스트를 작성하는 방법은 mdscruggs의 대답이며, 많은 문제가 있습니다 (낭비되는 메모리가 많고 느립니다). 물론 itandator로 팬더에 넣을 수 있습니다.이 경우에는 '판다'가 더 빨리 읽게하는 대신'csv'를 사용하는 것이 무엇입니까? – abarnert

+0

또한 ... 당신의 독자에게 방언 매개 변수 (적어도'구분자 = '\ t'')를 잊어 버렸습니다. – abarnert

+0

@abarnert : OP는 비용이 많이 들었 기 때문에 팬더를 원하지 않는다고 지정했기 때문에 많이 끝나지는 않을 것입니다. –

1

팬더를 사용하지 않으려면 numpy를 사용하는 것이 가장 좋습니다. numpy에는 전치 효과가 있으므로 열을 인덱스로 변경할 수 있습니다!

import csv 
import numpy as np 
with open('file_name.csv', 'rb') as f: 
    reading = csv.reader(f,delimiter='\t') 
    columns = reading.next() 
    hold_files = [] 
    for row in reading: 
     hold_files.append(row) 
    data = np.array(hold_files) 
    data = data.T 

해주기 data 각 항목은 각 열에 된 각 아이템을 포함하는 배열 인 배열! 아직도 값 비싸지 만 팬더는이 모든면에서 여전히 더 낫지 만 이것은 당신의 질문에 답해줍니다!

또한 pickle을 사용하여 디스크에 저장하는 것이 좋습니다. 더 많은 시간이 걸릴 것이지만, 다시 반복 할 필요는 없습니다! pickleFile

다음은 내가 방금 만든 배열을 저장합니다 :

import pickle 
def pickleSave(data, pickleFile): 
    output = open(pickleFile, 'wb') 
    pickle.dump(data, output) 
    output.close() 
    print "file has been saved to %s" % (pickleFile) 
def pickleLoad(pickleFile): 
    pkl_file = open(pickleFile, 'rb') 
    data = pickle.load(pkl_file) 
    pkl_file.close() 
    return data 

이, data 당신이 원하는 파일 이름 배열, dataframe 등 무엇이든 저장됩니다 : 여기에 당신이 그렇게 할 것입니다 방법입니다 ! 당신이 그 배열을 사용할 때마다

file_name = "my_array.txt" 
pickleSave(data,file_name) 

지금, 당신은 저장 한 다음 그것을로드 할 수

loaded_data = pickleLoad("my_array.txt") 

이제 변수 loaded_data 내가 이전에 만든 배열을 포함! 당신은 어떤 유형의 파일에도 이것을 사용할 수 있습니다!

2

여기에 두 가지 질문이 있습니다.내가 아는


가장 쉬운 해결책은 그러나 내 파일, 내가 어려움을 읽는 공연의 커플입니다되고, 팬더 패키지를 사용하는 것입니다. 그래서 나는 정상적인 스트리밍 방법을 사용하기로 결정했다.

하지 마십시오. Pandas는 순수 Python으로 작성한 것보다 훨씬 적은 메모리와 시간으로 많은 양의 데이터를 처리 할 수 ​​있습니다. 그리고 덜 모호하게도. numpy으로 내려간 다음 읽은 후에 결과를 판다는 것이 도움이되지만 순수한 파이썬으로 떨어지면 상황이 악화 될 수 있습니다.

코드에 문제가있는 경우 코드와 그에 상응하는 샘플 데이터를 생성하는 데 필요한 정보를 함께 표시하십시오. 여기


는, I는 각각 뱅크를 포함한 특정 열에있는 모든 값을 저장한다 (열 수가 ~ 500이다) 동적 열 변수를 생성 할. 예 : 변수 a는 목록 [11,22,31,, 42,555]입니다.

확실히하지 마십시오. 이와 같이 동적으로 변수를 생성하고 싶지는 않습니다. 거기에 이익이 없으며, 많은 단점이 있습니다.

사전과 정확히 일치합니다. 대신이의 : 당신이 이상의 모든 열을 반복하려면 대신,

column_dict['a'] 

을 그리고 :

column_dict = {column[0]: column[1:] for column in columns} 

그런 다음이처럼 액세스 할 수 있습니다

for column in columns: 
    create_variable_named(column[0]).set_to(column[1:]) 

그냥 이렇게 이것의 :

for col in a, b, c, d, …, zz, aaa, …: 

너 다만이 작업을 수행 할 수 있습니다

for col in column_dict.values(): 

당신은 정말, 정말, 당신이 할 수있는 동적 변수를 만들려면. 추가 할 범위 또는 네임 스페이스에 따라 다음 중 하나가됩니다.

globals()[name] = value 
locals()[name] = value 
setattr(module, name, value) 
setattr(obj, name, value) 
setattr(cls, name, value) 

... 등등. 코멘트에서

-1
def readAsCloumVec(fileName): 
    reader = open(fileName,'r') 
    text = reader.read() 
    lines = text.split('\n')#Split the text into lines 
    matrix = [] 
    for i in range(1,len(lines)): 
     if(len(lines[i])>0):#Ignore the last useless line 
      line = lines[i].split('\t')#The tag is depend on your file format 
      matrix.append(line) 
    cloumMatrix = [] 
    cloums = len(matrix[0]) 
    row = len(matrix) 
    print matrix  
    for j in range(cloums):#transposition the matrix 
     cloum = [] 
     for i in range(row):    
      cloum.append(matrix[i][j]) 
     cloumMatrix.append(cloum) 
    return cloumMatrix 

if __name__ == "__main__": 
    print readAsCloumVec('test.txt') 
1

:

그것은 메모리에 전체 파일을로드하고 영원히로드처럼 보인다 수 없습니다.

이 문제인 경우 잘못 공격하고있는 것입니다. 한 번에 전체 파일을 보관할 수있는 메모리가 충분하지 않은 경우 전체 배열을 한 번에 보유하지 못할 수도 있습니다.확실히은 순수한 Python 개체를 사용하는 경우에는 사용하지 않지만 pandas 또는 numpy을 사용하는 경우에는 사용할 수 없습니다.

그래서 디스크 기반 형식에서 다른 형식으로 변환 한 다음 원래 파일보다 훨씬 빠르게 디스크에서 데이터를 처리하도록 코드를 다시 작성해야합니다.

하나의 명백한 가능성은 탐색하거나 mmap을 통해 랜덤 액세스 할 수있는 파일입니다. 예를 들어, range(0, 1<<32)에 모두 맞는 값으로 된 500 개의 열이 있고 보유하고있는 행의 개수를 알 수 있다고 가정 해 보겠습니다.

행을 계산하기 위해 한 번만 csv를 반복 한 다음 4 * 500 * rows 바이트의 파일을 만든 다음 다시 csv를 반복하여 struct 모듈을 사용하여 작성합니다. 그런 다음 4 * rows * col, 4 * rows * (col+1) 이상의 mmap보기 만 생성하면 모든 열에 액세스 할 수 있습니다.

또는 대안 적으로 트랜스 포즈하십시오. 이것은 더 간단 해지고 I/O의 절반을 차지하지만 느려질 수 있습니다 (메모리 및 디스크 캐시 효과 모두로 인해).

만에 의해 열 랜덤 액세스해야하는 경우,하지 않음으로써 행, 단지 각 열에 대한 파일을 생성하고, 모든 열, 단지 mmap 해당 파일을 처리하기 위해, 또는 struct 또는 array을 통해 읽기, 또는 사용 pandas 또는 numpy 각각을 읽거나 쓸 수 있습니다 (또는 picklepandas 테이블/numpy 배열로 가능).

또 다른 가능성은 키 - 값 데이터베이스를 사용하여 파일에 해당하는 큰 blob을 저장하는 것입니다. 실제로 절편 테이블/배열을 계획하는 경우 shelve.shelf은 산세로 값을 보존하는 키 - 값 데이터베이스입니다.

이러한 아이디어를 임의로 선택하는 방법은 다음과 같습니다. 파일이 struct를 사용하여 즉석에서 트랜스, 데이터를 저장 :

것은 내가 당신에게 별도의 파일과 struct로 예를 들어 보겠습니다 : 이제

import csv 
import struct 

# You may want to check whether the column_foo.dat files already exist and are 
# at least as new as input.csv, so you don't re-generate them unless the input 
# data changes. That's obviously only a worthwhile optimization if you run the 
# script multiple times on the exact same input. 

with open('input.csv', 'rb') as f: 
    reader = csv.reader(f, delimiter='\t'): 
    column_names = next(reader) 
    column_files = [open('column_{}.dat'.format(column_name), 'wb') 
        for column_name in column_names] 
    for row in reader: 
     for i, col in enumerate(row): 
      value = int(col) 
      column_files[i].write(struct.pack('!I', value)) 
    for f in column_files: 
     f.close() 

을 나중에 열을 액세스하기 :

def get_column(name): 
    with open('column_{}.dat'.format(name), 'rb') as f: 
     fsize = os.path.getsize(f.fileno()) 
     length = fsize/4 
     fmt = '!{}I'.format(length) 
     return struct.unpack(fmt, f.read())