5

これは物事をよりよく理解するためです。私が修正する必要があるのは実際の問題ではありません。cstringIOオブジェクトは、文字列、ファイル、および行の反復子をエミュレートすることになっています。バッファもエミュレートしますか? いずれにせよ、理想的には、次のようにnumpy配列を構築できるはずです

import numpy as np
import cstringIO

c = cStringIO.StringIO('\x01\x00\x00\x00\x01\x00\x00\x00')

#Trying the iterartor abstraction
b = np.fromiter(c,int)
# The above fails with: ValueError: setting an array element with a sequence.

#Trying the file abstraction
b = np.fromfile(c,int)
# The above fails with: IOError: first argument must be an open file

#Trying the sequence abstraction
b = np.array(c, int)
# The above fails with: TypeError: long() argument must be a string or a number 

#Trying the string abstraction
b = np.fromstring(c)
#The above fails with: TypeError: argument 1 must be string or read-only buffer

b = np.fromstring(c.getvalue(), int)  # does work

私の質問は、なぜこのように振る舞うかということです。

これが発生した実際の問題は次のとおりです。タプルを生成するイテレータがあります。タプルのコンポーネントの1つから、コピーと複製をできるだけ少なくしてnumpy配列を作成することに興味があります。私の最初のカットは、生成されたタプルの興味深いコンポーネントを StringIO オブジェクトに書き込み続け、そのメモリ バッファーを配列に使用することでした。もちろん使用できますgetvalue()が、コピーを作成して返します。余分なコピーを避ける良い方法は何でしょうか。

4

2 に答える 2

3

問題は、numpy が数字の代わりに文字を与えられるのを好まないことです。Python では、単一の文字と文字列は同じ型を持つことを思い出してください'\x01'

もう 1 つの問題は、 acStringIOが文字ではなく行を反復することです。

次のイテレータのようなものは、これらの問題の両方を回避する必要があります。

def chariter(filelike):
    octet = filelike.read(1)
    while octet:
        yield ord(octet)
        octet = filelike.read(1)

次のように使用します (シークに注意してください!):

c.seek(0)
b = np.fromiter(chariter(c), int)
于 2011-06-24T11:05:35.017 に答える
2

ascStringIOはバッファ インターフェイスを実装していないためgetvalue、データのコピーを返す場合、コピーせずにデータを取得する方法はありません。

getvalueコピーを作成せずにバッファを文字列として返す場合はnumpy.frombuffer(x.getvalue(), dtype='S1')、追加のコピーなしで、文字列を参照する (読み取り専用の) numpy 配列を返します。


np.fromiter(c, int)andnp.array(c, int)が機能しない理由はcStringIO、 が反復されると、ファイルと同様に一度に 1 行ずつ返されるためです。

>>> list(iter(c))
['\x01\x00\x00\x00\x01\x00\x00\x00']

このような長い文字列は、単一の整数に変換できません。

***

本当に問題にならない限り、コピーの作成についてあまり心配しないのが最善です。その理由は、たとえばジェネレーターを使用してそれを に渡す場合の余分なオーバーヘッドは、numpy.fromiter実際にはリストを作成してそれを に渡す場合よりも大きい可能性があるためですnumpy.array--- コピーの作成は、Python のランタイム オーバーヘッドと比較して安価である可能性があります。

ただし、問題がメモリにある場合、1 つの解決策は、アイテムを最終的な Numpy 配列に直接配置することです。サイズが事前にわかっている場合は、事前に割り当てることができます。サイズが不明な場合は.resize()、配列内のメソッドを使用して、必要に応じてサイズを大きくすることができます。

于 2011-06-24T13:10:13.183 に答える