0

したがって、ファイルにサンプルデータがあります。これは次のように配置されています。

  u   v   w   p
 100 200 300 400 
 101 201 301 401
 102 202 302 402
 103 203 303 403 
 104 204 304 404
 105 205 305 405
 106 206 306 406
 107 207 307 407

ここで、最初の列を読み取ってリスト 'u' に保存し、2 番目の列をリスト 'v' に保存し、すべての列について 'p' まで保存します。これは私がこれまでに持っているものです:

import numpy as np
u  = []
v  = []
w  = []
p  = []

with open('testdata.dat') as f:
   for line in f:
       for x in line.split():
           u.append([int(x)])
           v.append([int(x)+1])
           w.append([int(x)+2])
           p.append([int(x)+3]) 

print 'u is'
print(u)
print 'v is'
print(v)
print 'w is'
print(w)
print 'p is'
print(p)

インデックスを変えてみましたが、出力が得られるので明らかに間違っています

u is
[[100], [200], [300], [400], [101], [201], [301], [401], [102], [202], [302], 
 [402], [103], [203], [303], [403], [104], [204], [304], [404], [105], [205], 
 [305], [405], [106], [206], [306], [406], [107], [207], [307], [407]]

v is
[[101], [201], [301], [401], [102], [202], [302], [402], [103], [203], [303], 
 [403], [104], [204], [304], [404], [105], [205], [305], [405], [106], [206], 
 [306], [406], [107], [207], [307], [407], [108], [208], [308], [408]]

w is
[[102], [202], [302], [402], [103], [203], [303], [403], [104], [204], [304], 
 [404], [105], [205], [305], [405], [106], [206], [306], [406], [107], [207], 
 [307], [407], [108], [208], [308], [408], [109], [209], [309], [409]]

p is
[[103], [203], [303], [403], [104], [204], [304], [404], [105], [205], [305], 
 [405], [106], [206], [306], [406], [107], [207], [307], [407], [108], [208], 
 [308], [408], [109], [209], [309], [409], [110], [210], [310], [410]]

インデックスによって行番号をインクリメントし、行全体を読み取りますが、サンプルデータで指定された名前に対応する別の変数に書き込まれるすべての列のデータが必要です-u = 100 --> 107、v = 200 --> 207など

Python でこれを行う方法についてのアイデアはありますか? (この操作は、非常に大きなデータセットに対して反復的に実行する必要があるため、高速で効率的なコードは非常に役立ちます)

4

3 に答える 3

2

内側のループを変更してください:

   for x in line.split():
       u.append([int(x)])
       v.append([int(x)+1])
       w.append([int(x)+2])
       p.append([int(x)+3]) 

   x = line.split()
   u.append([int(x[0])])
   v.append([int(x[1])])
   w.append([int(x[2])])
   p.append([int(x[3])])

元の実装では、「for x in line.split():」ループ内のステートメントが 4 回 (列ごとに) 実行されます。

于 2013-06-09T09:37:35.407 に答える
1

私がそれをよく理解していれば、Python の組み込み関数zipとを使用することで、mapそれを行うのに必要な行は 1 行だけです。

from itertools import izip

u,v,w,p = izip(*(map(int,line.split()) for line in open('data.txt')))

# Usage (Python3 syntax)
print("u is", list(u))
print("v is", list(v))
print("w is", list(w))
print("p is", list(p))

次の結果が生成されます。

u is [100, 101, 102, 103, 104, 105, 106, 107]
v is [200, 201, 202, 203, 204, 205, 206, 207]
w is [300, 301, 302, 303, 304, 305, 306, 307]
p is [400, 401, 402, 403, 404, 405, 406, 407]

これはあなたの懸念事項であるため、andを使用した暗黙的なループは、Python で実行するよりも優れたパフォーマンスを示すはずです (ループが非常に高速であっても)。このソリューションのメモリフットプリントが優れているかどうかはわかりません...zipmap

編集: python 2.xでもジェネレーターを使用するように置き換えられzipましたizip

于 2013-06-09T10:03:34.410 に答える
1

x.append([int(y)+c])1 つの要素のリストを追加します -int(y)+c

x.append(int(y)+c)シングルトンのリストではなく、数字のリストを取得する必要があります

ここにもかなりいい解決策があります

from itertools import izip

a="""1 2 3 4
10 20 30 40"""

lines= ([int(y) for y in x.split()] for x in a.split("\n"))
cols = izip(*lines)

print list(cols)

版画

[(1, 10), (2, 20), (3, 30), (4, 40)]

あなたのa.split("\n")場合はそうなるでしょopen("data").readlines()

これにより、ジェネレーターをリストに変換して計算を続行する場合を除き、任意の時点でデータ ファイルの 1 行のみをロードする必要があるため、メモリ パフォーマンスが大幅に向上します。

ただし、CPU に関してどのようにパフォーマンスが向上するかはわかりませんが、元のコードよりも少し優れているか、ほぼ同じであると推測されます。

これをベンチマークする場合は、ジェネレーターの代わりにリストのみを使用して pypy で試してみることも興味深いでしょう ( https://bitbucket.org/pypy/pypy/wiki/JitFriendlinessジェネレーターの見出しを参照してください)。それをメモリに。

データセットを考慮する

  (10**4 * 8 * 12)/1024.0

数値が比較的小さく、それぞれ 12 バイトかかると仮定すると ( Python: リストの各要素にはどのくらいのスペースが必要ですか? )、一度にすべてのデータを保持するために 1MB 弱のメモリが得られます。これは、メモリ消費量の点で非常に小さなデータ セットです。

于 2013-06-09T09:37:28.067 に答える