189

パンダを使用して一部のデータを操作しましたが、データベースにバッチ保存を実行したいと考えています。これには、データフレームをタプルの配列に変換する必要があり、各タプルはデータフレームの「行」に対応します。

私のデータフレームは次のようになります。

In [182]: data_set
Out[182]: 
  index data_date   data_1  data_2
0  14303 2012-02-17  24.75   25.03 
1  12009 2012-02-16  25.00   25.07 
2  11830 2012-02-15  24.99   25.15 
3  6274  2012-02-14  24.68   25.05 
4  2302  2012-02-13  24.62   24.77 
5  14085 2012-02-10  24.38   24.61 

次のようなタプルの配列に変換したい:

[(datetime.date(2012,2,17),24.75,25.03),
(datetime.date(2012,2,16),25.00,25.07),
...etc. ]

これを効率的に行う方法について何か提案はありますか?

4

10 に答える 10

247

どうですか:

subset = data_set[['data_date', 'data_1', 'data_2']]
tuples = [tuple(x) for x in subset.to_numpy()]

パンダの場合<0.24使用

tuples = [tuple(x) for x in subset.values]
于 2012-03-18T20:39:19.787 に答える
47

一般的な方法:

[tuple(x) for x in data_set.to_records(index=False)]
于 2012-12-05T19:42:50.703 に答える
44

動機
多くのデータセットは十分に大きいため、速度/効率を考慮する必要があります。だから私はその精神でこのソリューションを提供します。それはたまたま簡潔でもあります。

index比較のために、列を削除しましょう

df = data_set.drop('index', 1)

との使用を提案
しますzipmap

list(zip(*map(df.get, df)))

[('2012-02-17', 24.75, 25.03),
 ('2012-02-16', 25.0, 25.07),
 ('2012-02-15', 24.99, 25.15),
 ('2012-02-14', 24.68, 25.05),
 ('2012-02-13', 24.62, 24.77),
 ('2012-02-10', 24.38, 24.61)]

特定の列のサブセットを処理したい場合にも柔軟に対応できます。すでに表示されている列が必要なサブセットであると仮定します。

list(zip(*map(df.get, ['data_date', 'data_1', 'data_2'])))

[('2012-02-17', 24.75, 25.03),
 ('2012-02-16', 25.0, 25.07),
 ('2012-02-15', 24.99, 25.15),
 ('2012-02-14', 24.68, 25.05),
 ('2012-02-13', 24.62, 24.77),
 ('2012-02-10', 24.38, 24.61)]

より速いとは何ですか?

Turn's outrecordsが最も速く、その後に漸近的に収束zipmapし、iter_tuples

この投稿simple_benchmarksから取得したライブラリを使用します

from simple_benchmark import BenchmarkBuilder
b = BenchmarkBuilder()

import pandas as pd
import numpy as np

def tuple_comp(df): return [tuple(x) for x in df.to_numpy()]
def iter_namedtuples(df): return list(df.itertuples(index=False))
def iter_tuples(df): return list(df.itertuples(index=False, name=None))
def records(df): return df.to_records(index=False).tolist()
def zipmap(df): return list(zip(*map(df.get, df)))

funcs = [tuple_comp, iter_namedtuples, iter_tuples, records, zipmap]
for func in funcs:
    b.add_function()(func)

def creator(n):
    return pd.DataFrame({"A": random.randint(n, size=n), "B": random.randint(n, size=n)})

@b.add_arguments('Rows in DataFrame')
def argument_provider():
    for n in (10 ** (np.arange(4, 11) / 2)).astype(int):
        yield n, creator(n)

r = b.run()

結果を確認する

r.to_pandas_dataframe().pipe(lambda d: d.div(d.min(1), 0))

        tuple_comp  iter_namedtuples  iter_tuples   records    zipmap
100       2.905662          6.626308     3.450741  1.469471  1.000000
316       4.612692          4.814433     2.375874  1.096352  1.000000
1000      6.513121          4.106426     1.958293  1.000000  1.316303
3162      8.446138          4.082161     1.808339  1.000000  1.533605
10000     8.424483          3.621461     1.651831  1.000000  1.558592
31622     7.813803          3.386592     1.586483  1.000000  1.515478
100000    7.050572          3.162426     1.499977  1.000000  1.480131

r.plot()

ここに画像の説明を入力

于 2017-06-04T02:33:42.000 に答える
9

この回答は、まだ議論されていない回答を追加しませんが、速度の結果をいくつか示します。これにより、コメントで出てきた質問が解決されるはずです。これらの 3 つの値に基づいて、これらはすべてO(n)のように見えます。

TL;DR :tuples = list(df.itertuples(index=False, name=None))そしてtuples = list(zip(*[df[c].values.tolist() for c in df]))最速で結ばれています.

ここで、3 つの提案の結果について簡単な速度テストを行いました。

  1. @pirsquared からの zip 回答:tuples = list(zip(*[df[c].values.tolist() for c in df]))
  2. @ wes-mckinneyからの受け入れられた回答:tuples = [tuple(x) for x in df.values]
  3. @Axel からのname=None提案による @ksindi からの itertuples の回答:tuples = list(df.itertuples(index=False, name=None))
from numpy import random
import pandas as pd


def create_random_df(n):
    return pd.DataFrame({"A": random.randint(n, size=n), "B": random.randint(n, size=n)})

小さいサイズ:

df = create_random_df(10000)
%timeit tuples = list(zip(*[df[c].values.tolist() for c in df]))
%timeit tuples = [tuple(x) for x in df.values]
%timeit tuples = list(df.itertuples(index=False, name=None))

与えます:

1.66 ms ± 200 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
15.5 ms ± 1.52 ms per loop (mean ± std. dev. of 7 runs, 100 loops each)
1.74 ms ± 75.4 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

大きい:

df = create_random_df(1000000)
%timeit tuples = list(zip(*[df[c].values.tolist() for c in df]))
%timeit tuples = [tuple(x) for x in df.values]
%timeit tuples = list(df.itertuples(index=False, name=None))

与えます:

202 ms ± 5.91 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
1.52 s ± 98.1 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
209 ms ± 11.8 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

私が持っている限りの忍耐:

df = create_random_df(10000000)
%timeit tuples = list(zip(*[df[c].values.tolist() for c in df]))
%timeit tuples = [tuple(x) for x in df.values]
%timeit tuples = list(df.itertuples(index=False, name=None))

与えます:

1.78 s ± 118 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
15.4 s ± 222 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
1.68 s ± 96.3 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

zip バージョンと itertuples バージョンは、互いに信頼区間内にあります。彼らはボンネットの下で同じことをしているのではないかと思います。

ただし、これらの速度テストはおそらく無関係です。コンピューターのメモリの限界を超えるのにそれほど時間はかかりません。大規模なデータ セットに対してこれを行うべきではありませんこれを行った後にそれらのタプルを操作すると、非常に非効率的になります。これがコードの大きなボトルネックになる可能性は低いので、最も読みやすいと思われるバージョンをそのまま使用してください。

于 2019-03-01T20:59:59.323 に答える
3
#try this one:

tuples = list(zip(data_set["data_date"], data_set["data_1"],data_set["data_2"]))
print (tuples)
于 2017-10-09T19:11:29.667 に答える