2017-04-27 9 views
0

Cython에서 행별로 읽은 데이터 세트가 있습니다. 각 행은 문자열로 반환됩니다. 내가 뭘하고 싶은 건 문자열을 각 행의 열의 수와 같은 길이의 정수 (ints와 floats) 배열로 변환하는 것입니다 (';'로 표시). cython - 문자열을 정수 및 부동 소수점으로 변환

import pandas as pd 
import numpy as np 

df = pd.DataFrame(np.c_[np.random.rand(3,2),np.random.randint(0,10,(3,2))], columns = ['a','b','c','d']) 

filename = r'H:\mydata.csv' 
df.to_csv('filename',sep=';',index=False) 

예를

를 들어

는 지금은 무작위 사이 썬의 행을 반복하고 각 행에 대한 몇 가지 계산을 수행합니다. 다음과 같이

import numpy as np 
from readc_csv import row_pos, read_file_and_compute 

filename = r'H:\mydata.csv' 
row_position = row_pos(filename)[:-1] # returns the position of the start 
             # of each row in the file 
             # (excluding the header) 

rows = np.random.choice(row_position,size=len(row_position),replace=False) 
read_file_and_compute(filename,rows) 

readc_csv.pyx 파일을 찾습니다

from libc.stdio cimport FILE, fopen, fgets, fclose, fseek, SEEK_SET, ftell 
import numpy as np 
cimport numpy as np 

def row_pos(str filename): 
    filename_byte_string = filename.encode("UTF-8") 

    cdef: 
     char* fname = filename_byte_string 
     FILE* cfile 
     char line[50] 
     list pos = [] 

    cfile = fopen(fname, "r") 

    while fgets(line, 50, cfile)!=NULL: 
     pos.append(ftell(cfile)) 

    fclose(cfile) 

    return pos    


def read_file_and_compute(str filename, int [:] rows): 
    filename_byte_string = filename.encode("UTF-8") 
    cdef: 
     char* fname = filename_byte_string 
     FILE* cfile 
     char line[50] 
     size_t j 
     int n = rows.shape[0] 

    cfile = fopen(fname, "r") 

    for j in range(n): 
     r = rows[j] 
     fseek(cfile,r,SEEK_SET) 
     fgets(line, 50, cfile) 

     # line is now e.g. 
     # '0.659933520847;0.471779123704;1.0;2.0\n' 
     # I want to convert it into an array with 4 elements 
     # each element corresponding to one of the numbers we 
     # see in the string 
     # and do some computations 


    fclose(cfile) 

    return 

(참고 : 사이 썬 코드는 아직 optimzed되지 않음) Backround입니다 정보 :이 내가 확률 그라데이션을 위해 쓰고 싶은 스크립트의 일부입니다 메모리로 읽어 들일 수 없을만큼 큰 데이터 세트에 대한 강하. cython에서 임의로 정렬 된 샘플을 통해 내부 루프를 수행하려고합니다. 따라서 나는 cython에서 csv 파일의 주어진 행에서 데이터를 읽을 수 있어야합니다.

+0

이것은 내가 생각하기에 지점을 놓친 답변에서 취한 유용한 의견이라고 생각합니다 (그래서 삭제했습니다) : CSV 대신 이진 파일을 사용할 수 있다면 [numpy는 메모리 매핑 배열이라는 기능이 있습니다] https://docs.scipy.org/doc/numpy/reference/generated/numpy.memmap.html) 바이너리 파일 용으로 이것을 구현합니다. 이것은 자신의 글을 작성하는 것보다 훨씬 쉽습니다. – DavidW

+0

도움이 될만한 두 번째 주석 : 다음 Python 코드는'return np.array ([str (line) .split (';')])에서'l에 대해 float (l)을 반환합니다. 최적화되지 않았지만 더 나은 것을 찾으려고 할 때 이것을 자리 표시 자로 사용할 수 있습니다. – DavidW

답변

0

libc.stringlibc.stdlib에서 가져올 수있는 strtokatof이 발견되었습니다. 그들은 트릭을합니다.

위의 예에게 read_file_and_compute 기능을 계속하는 것은 다음 다른 유형으로 문자열 변환을위한 더 많은 기능이 있습니다이

def read_file_and_compute(str filename, int [:] rows, int col_n): 
    filename_byte_string = filename.encode("UTF-8") 
    cdef: 
     char* fname = filename_byte_string 
     FILE* cfile 
     char line[50] 
     char *token 
     double *col = <double *>malloc(col_n * sizeof(double)) 
     size_t j, i 
     int count 
     double num 
     int n = rows.shape[0] 

    cfile = fopen(fname, "r") 

    for j in range(n): 
     r = rows[j] 
     fseek(cfile,r,SEEK_SET) 
     fgets(line, 50, cfile) 

     token = strtok(line, ';') # splits the string at the delimiter ';' 
     count = 0 
     while token!=NULL and count<col_n: 
      num = atof(token) # converts the string into a float 

      col[count] = num 
      token = strtok(NULL,';\n') 
      count +=1 

     # now do some computations on col ... 

fclose(cfile) 
free(col)  

return 

같이 보일 수 here를 참조하십시오.

+0

경고의 한 단어 :'strtok'는 쓰레드에 안전하다는 보장이 없으므로, 당신이 주로 C 기반 구현을하게 된 이유는 병렬로 작업을 실행하는 것입니다. 병렬로 여러 버전을 실행하지 않으려면 걱정하지 마십시오. – DavidW