我已经使用pandas操纵了一些数据,现在我想执行批量保存回数据库.这需要我将数据帧转换为元组数组,每个元组对应于数据帧的"行".
我的DataFrame看起来像:
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
Run Code Online (Sandbox Code Playgroud)
我想将它转换为元组数组,如:
[(datetime.date(2012,2,17),24.75,25.03),
(datetime.date(2012,2,16),25.00,25.07),
...etc. ]
Run Code Online (Sandbox Code Playgroud)
关于如何有效地做到这一点的任何建议?
Wes*_*ney 176
怎么样:
subset = data_set[['data_date', 'data_1', 'data_2']]
tuples = [tuple(x) for x in subset.values]
Run Code Online (Sandbox Code Playgroud)
ksi*_*ndi 117
list(data_set.itertuples(index=False))
Run Code Online (Sandbox Code Playgroud)
从17.1开始,上面将返回一个namedtuples列表 - 请参阅文档.
Ram*_*gil 43
通用方式:
[tuple(x) for x in data_set.to_records(index=False)]
Run Code Online (Sandbox Code Playgroud)
piR*_*red 19
动机
许多数据集足够大,我们需要关注速度/效率.所以我本着这种精神提供这种解决方案.它恰好也很简洁.
为了便于比较,让我们放弃index列
df = data_set.drop('index', 1)
Run Code Online (Sandbox Code Playgroud)
解决方案
我将提出使用zip和理解
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)]
Run Code Online (Sandbox Code Playgroud)
如果我们想处理特定的列子集,它恰好也是灵活的.我们假设我们已经显示的列是我们想要的子集.
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)]
Run Code Online (Sandbox Code Playgroud)
以下所有产生相同的结果
maprecordszipmapiter_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()
Run Code Online (Sandbox Code Playgroud)
小数据
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
Run Code Online (Sandbox Code Playgroud)
大数据
r.plot()
Run Code Online (Sandbox Code Playgroud)
Gow*_*amy 14
将数据框列表更改为元组列表。
df = pd.DataFrame({'col1': [1, 2, 3], 'col2': [4, 5, 6]})
print(df)
OUTPUT
col1 col2
0 1 4
1 2 5
2 3 6
records = df.to_records(index=False)
result = list(records)
print(result)
OUTPUT
[(1, 4), (2, 5), (3, 6)]
Run Code Online (Sandbox Code Playgroud)
Nic*_*eli 11
这里的一个矢量化的方法(假设数据帧,data_set将被定义df返回一个代替)list的tuples,如下所示:
>>> df.set_index(['data_date'])[['data_1', 'data_2']].to_records().tolist()
Run Code Online (Sandbox Code Playgroud)
生产:
[(datetime.datetime(2012, 2, 17, 0, 0), 24.75, 25.03),
(datetime.datetime(2012, 2, 16, 0, 0), 25.0, 25.07),
(datetime.datetime(2012, 2, 15, 0, 0), 24.99, 25.15),
(datetime.datetime(2012, 2, 14, 0, 0), 24.68, 25.05),
(datetime.datetime(2012, 2, 13, 0, 0), 24.62, 24.77),
(datetime.datetime(2012, 2, 10, 0, 0), 24.38, 24.61)]
Run Code Online (Sandbox Code Playgroud)
将datetime列设置为索引轴的想法是通过利用对数据帧执行此操作的参数来帮助将Timestamp值转换为相应的datetime.datetime格式.convert_datetime64DF.to_recordsDateTimeIndex
这将返回一个recarray然后可以返回list使用.tolist
根据用例,更通用的解决方案是:
df.to_records().tolist() # Supply index=False to exclude index
Run Code Online (Sandbox Code Playgroud)
该答案不会添加尚未讨论的任何答案,但是这里提供了一些速度结果。我认为这应该可以解决评论中出现的问题。基于这三个值,所有这些看起来都像是O(n)。
TL; DR:tuples = list(df.itertuples(index=False, name=None))和tuples = list(zip(*[df[c].values.tolist() for c in df]))并列最快。
我对结果进行了快速速度测试,其中包含三个建议:
tuples = list(zip(*[df[c].values.tolist() for c in df]))tuples = [tuple(x) for x in df.values]name=None建议: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)})
Run Code Online (Sandbox Code Playgroud)
小尺寸:
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))
Run Code Online (Sandbox Code Playgroud)
给出:
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)
Run Code Online (Sandbox Code Playgroud)
较大:
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))
Run Code Online (Sandbox Code Playgroud)
给出:
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)
Run Code Online (Sandbox Code Playgroud)
尽我所能:
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))
Run Code Online (Sandbox Code Playgroud)
给出:
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)
Run Code Online (Sandbox Code Playgroud)
zip版本和itertuples版本彼此在置信区间内。我怀疑他们在幕后做着同样的事情。
这些速度测试可能无关紧要。突破计算机内存的限制并不需要花费大量时间,并且您实际上不应该对大型数据集执行此操作。完成这些操作后,使用这些元组将最终效率低下。它不太可能成为代码中的主要瓶颈,因此,请坚持使用您认为最易读的版本。
最有效,最简单的方法:
list(data_set.to_records())
Run Code Online (Sandbox Code Playgroud)
您可以在此调用之前过滤所需的列。