Панды преобразуют фрейм данных в массив кортежей


Я манипулировал некоторыми данными с помощью панд, и теперь я хочу выполнить пакетное сохранение обратно в базу данных. Это требует от меня преобразования фрейма данных в массив кортежей, причем каждый кортеж соответствует "строке" фрейма данных.

мой фрейм данных выглядит примерно так:

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

любые предложения о том, как я могу эффективно сделать это?

7 62

7 ответов:

Как насчет:

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

начиная с 17.1, выше будет возвращен список namedtuples-см. docs.

общее:

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

мотивация
Многие наборы данных достаточно велики, что мы должны заботиться о скорости/эффективности. Поэтому я предлагаю это решение в таком духе. Это также бывает кратким.

Для сравнения, давайте отбросим 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)]

он также может быть гибким, если мы хотим иметь дело с a конкретное подмножество столбцов. Мы предположим, что столбцы, которые мы уже показали, являются подмножеством, которое мы хотим.

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

вот векторизованный подход (предполагая фрейм данных,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 в качестве оси индекса заключается в том, чтобы помочь в преобразовании Timestamp значение ему соответствует datetime.datetime эквивалент формата, используя

более подходящие для Python образом:

df = data_set[['data_date', 'data_1', 'data_2']]
map(tuple,df.values)
#try this one:

tuples = list(zip(data_set["data_date"], data_set["data_1"],data_set["data_2"]))
print (tuples)