Pandas将数据帧转换为元组数组

时间:2012-03-18 12:53:07

标签: python pandas

我使用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 

我想将其转换为元组数组,如:

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

关于如何有效地做到这一点的任何建议?

10 个答案:

答案 0 :(得分:147)

怎么样:

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

答案 1 :(得分:88)

list(data_set.itertuples(index=False))

从17.1开始,上述内容将返回list of namedtuples

如果您想要一个普通元组列表,请将name=None作为参数传递:

list(data_set.itertuples(index=False, name=None))

答案 2 :(得分:41)

通用方式:

[tuple(x) for x in data_set.to_records(index=False)]

答案 3 :(得分:15)

<强>动机
许多数据集足够大,我们需要关注速度/效率。所以我本着这种精神提供这种解决方案。它恰好也很简洁。

为了便于比较,我们放弃index

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

<强>解决方案
我建议使用zip和理解

list(zip(*[df[c].values.tolist() for c in 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(*[df[c].values.tolist() for c in ['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)]

以下所有内容产生相同的结果

  • [tuple(x) for x in df.values]
  • df.to_records(index=False).tolist()
  • list(map(tuple,df.values))
  • list(map(tuple, df.itertuples(index=False)))

什么更快?
zip并且理解力更快

%timeit [tuple(x) for x in df.values]
%timeit list(map(tuple, df.itertuples(index=False)))
%timeit df.to_records(index=False).tolist()
%timeit list(map(tuple,df.values))
%timeit list(zip(*[df[c].values.tolist() for c in df]))

小数据

10000 loops, best of 3: 55.7 µs per loop
1000 loops, best of 3: 596 µs per loop
10000 loops, best of 3: 38.2 µs per loop
10000 loops, best of 3: 54.3 µs per loop
100000 loops, best of 3: 12.9 µs per loop

大数据

10 loops, best of 3: 58.8 ms per loop
10 loops, best of 3: 43.9 ms per loop
10 loops, best of 3: 29.3 ms per loop
10 loops, best of 3: 53.7 ms per loop
100 loops, best of 3: 6.09 ms per loop

答案 4 :(得分:9)

此处采用矢量化方法(假设数据框,data_set定义为df),返回list tuples,如下所示:

>>> df.set_index(['data_date'])[['data_1', 'data_2']].to_records().tolist()

产生

[(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)]

将datetime列设置为索引轴的想法是通过使用{{1}来帮助将Timestamp值转换为相应的datetime.datetime格式等效值} DF.to_records中的参数,对convert_datetime64数据帧执行此操作。

这会返回DateTimeIndex,然后可以使用recarray

返回list

根据用例,更通用的解决方案是:

.tolist

答案 5 :(得分:6)

此答案不会添加尚未讨论的任何答案,但是此处列出了一些速度结果。我认为这应该可以解决评论中出现的问题。基于这三个值,所有这些看起来都是 O(n)

TL; DR tuples = list(df.itertuples(index=False, name=None))tuples = list(zip(*[df[c].values.tolist() for c in df]))并列最快。

我在这里对结果进行了快速测试,提出了三个建议:

  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. @ksindi的itertuples答案与@Axel的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)})

小尺寸:

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版本在置信区间内。我怀疑他们在后台做同样的事情。

这些速度测试可能无关紧要。突破计算机内存的限制不会花费大量时间,并且您真的不应该在大型数据集上执行此操作。完成这些操作后,使用这些元组将最终效率低下。这不太可能成为代码中的主要瓶颈,所以请坚持使用您认为最易读的版本。

答案 6 :(得分:4)

将数据框架列表更改为元组列表。

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)]

答案 7 :(得分:2)

更多pythonic方式:

df = data_set[['data_date', 'data_1', 'data_2']]
map(tuple,df.values)

答案 8 :(得分:2)

double highest = (double)numbers.get(0);
       for(int i = 0; i < numbers.size(); i++){
           int compare = Double.compare(highest, (double)numbers.get(i));
       if(compare < 0){
          highest = (double)numbers.get(i);
        }

        System.out.print(highest+"   ");
       }

答案 9 :(得分:0)

最有效,最简单的方法:

list(data_set.to_records())

您可以在此调用之前过滤所需的列。