0

次の3列形式のデータセット(CSVファイル)があります。

A, B, C
3277,4733,54.1 
3278,4741,51.0 
3278,4750,28.4 
3278,4768,36.0 
3278,4776,50.1 
3278,4784,51.4 
3279,4792,82.6 
3279,4806,78.2 
3279,4814,36.4 

そして、私は次のような3分割分割表を取得する必要があります:(申し訳ありませんが、これは完全に良く見えません)

A /B     4733      4741      4750      4768      4776      4784      4792      4806      4814
3277   C 54.1                                                
3278                 51      28.4        36      50.1      51.4                  
3279                                                                 82.6      78.2      36.4

優れた「ピボットテーブル」、OpenOfficeデータパイロット、またはR「テーブル(x、y、z)」と同様に

問題は、私のデータセットが巨大であるということです(合計500,000行を超え、AとBに約400の異なる要素があります(OOo、MSO、およびRの制限によりこれを達成できません)

Pythonスクリプトを使用して、このようなテーブルを作成できると確信しています。AとBはどちらも数値です(ただし、文字列として扱うことができます)。

誰かがこれに対処しましたか?(擬似コードまたはCまたはJavaのコードも歓迎されます...しかし、実装が高速であるため、Pythonの方が好きです:)

編集: ジョン・マチンのおかげで、ほとんどそれを持っています。次のPythonスクリプトは、私が探しているものをほぼ提供しますが、出力ファイルを書き込むと、(最初の行から取得した)「ヘッダー」の値が他の行に対応していないことがわかります。

from collections import defaultdict as dd
d = dd(lambda: dd(float))

input =  open("input.txt")
output = open("output.txt","w")
while 1:
    line = input.readline()
    if not line:
        break
    line = line.strip('\n').strip('\r')
    splitLine = line.split(',')
    if (len(splitLine) <3):
        break
    d[splitLine[0]][splitLine[1]] = splitLine[2]

output.write("\t")
for k,v in d.items()[0][1].items():
    output.write(str(k)+"\t")
output.write("\n")
for k,v in d.items():
    output.write(k+"\t")
    for k2,v2 in v.items():
        output.write(str(v2)+"\t")
    output.write("\n")
4

6 に答える 6

1

RIではこれを行うことができます:

N <- 1000000
x <- sample(1:400,N,TRUE)
y <- sample(1:400,N,TRUE)
z <- sample(1:400,N,TRUE)

w <- table(x,y,z)

また、メモリのピークは800MB未満です。

では、どのような制限がありますか?


編集。このRコードの平和:

N <- 1000000
mydata <- data.frame(
    A=sample(runif(400),N,TRUE),
    B=sample(runif(400),N,TRUE),
    C=runif(N)
)

require(reshape)
results <- cast(mydata, A~B, value="C")
write.table(as.matrix(results),na="",sep="\t",file="results.txt")

300MB未満のRAMで必要なものを作成します。

私のデータでは、一意でないABの組み合わせがあるという警告が表示されますが、あなたにとっては問題ないはずです。

于 2010-10-28T16:24:47.263 に答える
1

あなたが持っているのはハンマーだけのとき。。。。。

概念的には、実行しようとしていることは単純ですが、データのサイズが原因で、計算が困難です。私は、データラングリングスキルではなく、分析能力とグラフィックス能力のためにRを使用する傾向があります。大量のデータを移動する必要がある場合、通常はすべてをデータベースに貼り付けます。

最近、私はSQLiteとRでかなりの成功を収めています。最良の部分は、実際にRを使用してデータを読み込むことができることです。これにより、SQLiteでは実際にはできない大きなSPSSファイルやその他のデータソースを簡単にインポートできます。ハンドルしますが、Rはできます。

http://cran.r-project.org/web/packages/RSQLite/index.html

これが私の推奨ワークフローです。

  1. データをRにインポートします。(完了)
  2. ライブラリ(RSQLite)
  3. データフレームをSQLiteに移動します。
  4. 列AとBにインデックスを作成します。
  5. テーブルを作成するビューを作成します。
  6. Rからビューを照会し、リターンをテーブルに強制します。
于 2010-10-28T16:21:13.520 に答える
1

まったく新しい話は、まったく新しい答えに値します。

defaultdictは必要ありません。また、defaultdictを不注意に使用すると、DeathStarのトラクタービームのようにメモリが消費されるためです。

このコードはテストされておらず、コンパイルすらできない可能性があります。行と列をどこかで入れ替えた可能性があります。後で修正/説明...急ぐ必要があります...

d = {}
col_label_set = set()
row_label_set = set()
input =  open("input.txt")
output = open("output.txt","w")
for line in input:
    line = line.strip()
    splat = line.split(',')
    if len(splat) != 3:
        break # error message???
    k1, k2, v = splat
    try:
        subdict = d[k1]
    except KeyError:
        subdict = {}
        d[k1] = subdict
    subdict[k2] = v
    row_label_set.add(k1)
    col_label_set.add(k2)
col_labels = sorted(col_label_set)
row_labels = sorted(row_label_set
output.write("\t")
for v in col_labels::
    output.write(v + "\t")
output.write("\n")
for r in row_labels:
    output.write(r + "\t")
    for c in col_labels:
        output.write(d[r].get(c, "") + "\t")
    output.write("\n")

更新これは、示されている範囲でテストされた、修正およびリファクタリングされたバージョンです。

class SparseTable(object):

    def __init__(self, iterable):
        d = {}
        col_label_set = set()
        for row_label, col_label, value in iterable:
            try:
                subdict = d[row_label]
            except KeyError:
                subdict = {}
                d[row_label] = subdict
            subdict[col_label] = value
            col_label_set.add(col_label)
        self.d = d
        self.col_label_set = col_label_set

    def tabulate(self, row_writer, corner_label=u"", missing=u""):
        d = self.d
        col_labels = sorted(self.col_label_set)
        row_labels = sorted(d.iterkeys())
        orow = [corner_label] + col_labels
        row_writer(orow)
        for row_label in row_labels:
            orow = [row_label]
            subdict = d[row_label]
            for col_label in col_labels:
                orow.append(subdict.get(col_label, missing))
            row_writer(orow)

if __name__ == "__main__":

    import sys

    test_data = u"""
    3277,4733,54.1
    3278,4741,51.0
    3278,4750,28.4
    3278,4768,36.0
    3278,4776,50.1
    3278,4784,51.4
    3279,4792,82.6
    3279,4806,78.2
    3279,4814,36.4
    """.splitlines(True)

    def my_writer(row):
        sys.stdout.write(u"\t".join(row))
        sys.stdout.write(u"\n")

    def my_reader(iterable):
        for line in iterable:
            line = line.strip()
            if not line: continue
            splat = line.split(u",")
            if len(splat) != 3:
                raise ValueError(u"expected 3 fields, found %d" % len(splat))
            yield splat

    table = SparseTable(my_reader(test_data))
    table.tabulate(my_writer, u"A/B", u"....")

出力は次のとおりです。

A/B     4733    4741    4750    4768    4776    4784    4792    4806    4814
3277    54.1    ....    ....    ....    ....    ....    ....    ....    ....
3278    ....    51.0    28.4    36.0    50.1    51.4    ....    ....    ....
3279    ....    ....    ....    ....    ....    ....    82.6    78.2    36.4
于 2010-10-29T11:26:29.153 に答える
0

必要な出力の例は、私には3分割分割表のようには見えません。これは、(key1、key2、key3)から発生回数へのマッピングになります。この例は、(key1、key2)からいくつかの数値へのマッピングのように見えます。(key1、key2)が複製されたときに何をすべきかを言わないでください:平均、合計、他の何か?

合計が必要であると仮定して、ネストされたdefaultdictsを使用したPythonでのメモリ節約アプローチを次に示します。

>>> from collections import defaultdict as dd
>>> d = dd(lambda: dd(float))
>>> d[3277][4733] += 54.1
>>> d
defaultdict(<function <lambda> at 0x00D61DF0>, {3277: defaultdict(<type 'float'>, {4733: 54.1})})
>>> d[3278][4741] += 51.0
>>> d
defaultdict(<function <lambda> at 0x00D61DF0>, {3277: defaultdict(<type 'float'>, {4733: 54.1}), 3278: defaultdict(<type 'float'>, {4741: 51.0})})
>>>

defaultdict複合キーを持つシングルを使用する別のアプローチ:

>>> d2 = dd(float)
>>> d2[3277,4733] += 54.1
>>> d2
defaultdict(<type 'float'>, {(3277, 4733): 54.1})
>>> d2[3278,4741] += 51.0
>>> d2
defaultdict(<type 'float'>, {(3277, 4733): 54.1, (3278, 4741): 51.0})
>>>

グループ化した後、このデータで何をしたいのかを言うと役立つかもしれません...

(たとえば)平均が必要な場合は、2つのオプションがあります。(1)2つのデータ構造(1つは合計用、もう1つはカウント用)、次に「平均=合計-カウント」を実行します(2)最初の2列でデータを並べ替えます、user itertools.groupbyを使用して、重複を収集し、計算を実行して、結果を「平均」データ構造に追加します。これらのアプローチのどれがより少ないメモリを使用するかを判断するのは困難です。PythonはPythonなので、両方をかなりすばやく試すことができます。

于 2010-10-28T20:09:07.360 に答える
0

Rで使用できる場合はtable(x,y,z)、このような巨大なデータセットを処理するメモリパッケージからRを試してみてはどうでしょうか。パッケージbigmemoryread.big.matrixの関数を使用してデータセットを読み込み、パッケージbigtabulateの関数bigtableを使用してテーブルを作成します。

ビネットを参照してください。

于 2010-10-28T16:23:45.307 に答える
0

dictの小さなサブクラスは、テーブルを操作するための快適なオブジェクトを提供できます。500.000アイテムはデスクトップPCでは問題になりません-500.000.000アイテムがある場合、同様のクラスがキーからファイル自体の位置にマップされる可能性があります(実装する方がはるかにクールです:-))

import csv
class ContingencyTable(dict):
    def __init__(self):
        self.a_keys=set()
        self.b_keys=set()
        dict.__init__(self)
    def __setitem__(self, key,value):
        self.a_keys.add(key[0])
        self.b_keys.add(key[1])
        dict.__setitem__(self, key, value)
    def feed(self, file):
        reader = csv.reader(file)
        reader.next()
        for a, b, c in reader:
            self[int(a),int(b)] = float(c)

table = ContingencyTable()
table.feed(open("yourfile.csv"))
于 2010-10-28T20:16:17.067 に答える