2017-04-27 15 views
0

私はCythonの行ごとに読み込んだデータセットを持っています。各行は文字列として返されます。私がしたいのは、文字列を各行の列数(区切り文字 ';'で与えられる)と等しい長さの数値(整数と浮動小数点数)の配列に変換することです。例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) 

については

は、今私はcython内の行の上にランダムに反復処理し、各行のいくつかの計算をしたいです。次のように

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 

(注:cythonコードがまだoptimzedされていない) backroundの情報:これは私が確率的勾配のために書きたいスクリプトの一部でありますメモリーに読み込むには大きすぎるデータ・セットに降下します。私はcythonのランダムに順序付けられたサンプルの上で内部ループを実行したい。したがって、私はcsvファイル内の特定の行からcythonでデータを読み取ることができる必要があります。

+0

これは、ポイントを逃した答え(そして私が削除したもの)から得られる有用なコメントだと思います:csvの代わりにバイナリファイルを使用できる場合、[numpyにはメモリマップされた配列という機能があります] https://docs.scipy.org/doc/numpy/reference/generated/numpy.memmap.html)バイナリファイル用にこれを実装しています。これはあなた自身のものを書くよりもはるかに簡単です。 – DavidW

+0

次のようなPythonコードは、 'return np.array([str(line).split( ';')])の' return np.array(float最適化されていませんが、より良いものを見つけようとするときにプレースホルダとして使用できます。 – DavidW

答えて

0

libc.stringおよびlibc.stdlibからインポートできるc-functions strtokおよびatofが見つかりました。彼らはトリックを行う。

上記の例に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

関連する問題