Як сформувати стовпчик кортежу з двох стовпців у Пандах


125

У мене є DataFrame Pandas, і я хочу поєднати стовпці "lat" і "long", щоб сформувати кортеж.

<class 'pandas.core.frame.DataFrame'>
Int64Index: 205482 entries, 0 to 209018
Data columns:
Month           205482  non-null values
Reported by     205482  non-null values
Falls within    205482  non-null values
Easting         205482  non-null values
Northing        205482  non-null values
Location        205482  non-null values
Crime type      205482  non-null values
long            205482  non-null values
lat             205482  non-null values
dtypes: float64(4), object(5)

Я намагався використовувати:

def merge_two_cols(series): 
    return (series['lat'], series['long'])

sample['lat_long'] = sample.apply(merge_two_cols, axis=1)

Однак це повернуло таку помилку:

---------------------------------------------------------------------------
 AssertionError                            Traceback (most recent call last)
<ipython-input-261-e752e52a96e6> in <module>()
      2     return (series['lat'], series['long'])
      3 
----> 4 sample['lat_long'] = sample.apply(merge_two_cols, axis=1)
      5

...

AssertionError: Block shape incompatible with manager 

Як я можу вирішити цю проблему?

Відповіді:


201

Будьте комфортні zip. Це стане в нагоді при роботі з даними стовпців.

df['new_col'] = list(zip(df.lat, df.long))

Це менш складно і швидше, ніж використання applyабо map. Щось подібне np.dstackвдвічі швидше zip, але не дасть вам кортежів.


3
в python3, ви повинні використовувати list. Це має спрацювати:df['new_col'] = list(zip(df.lat, df.long))
Паульвазіт

@paulwasit ах, так, мої ненависні стосунки до ледачої поведінки python 3. Дякую.
Дейл Юнг

4
Цей метод list(zip(df.lat, df.long))у 124 мс набагато ефективніший, ніж df[['lat', 'long']].apply(tuple, axis=1)у 14,2 с для 900k рядків. Співвідношення більше 100.
Пенджу Чжао

1
Я намагаюся використовувати це з більш довгим списком стовпців, df['new_col'] = list(zip(df[cols_to_keep])) але продовжую отримувати помилку: Length of values does not match length of indexбудь-яка порада?
seeiespi

1
@ Відповідь ПетерГансена допомогла мені, але подумайте, що, можливо, не вистачає * для розпакування списку спочатку - тобто df['new_col'] = list(zip(*[df[c] for c in cols_to_keep])
jedge

61
In [10]: df
Out[10]:
          A         B       lat      long
0  1.428987  0.614405  0.484370 -0.628298
1 -0.485747  0.275096  0.497116  1.047605
2  0.822527  0.340689  2.120676 -2.436831
3  0.384719 -0.042070  1.426703 -0.634355
4 -0.937442  2.520756 -1.662615 -1.377490
5 -0.154816  0.617671 -0.090484 -0.191906
6 -0.705177 -1.086138 -0.629708  1.332853
7  0.637496 -0.643773 -0.492668 -0.777344
8  1.109497 -0.610165  0.260325  2.533383
9 -1.224584  0.117668  1.304369 -0.152561

In [11]: df['lat_long'] = df[['lat', 'long']].apply(tuple, axis=1)

In [12]: df
Out[12]:
          A         B       lat      long                             lat_long
0  1.428987  0.614405  0.484370 -0.628298      (0.484370195967, -0.6282975278)
1 -0.485747  0.275096  0.497116  1.047605      (0.497115615839, 1.04760475074)
2  0.822527  0.340689  2.120676 -2.436831      (2.12067574274, -2.43683074367)
3  0.384719 -0.042070  1.426703 -0.634355      (1.42670326172, -0.63435462504)
4 -0.937442  2.520756 -1.662615 -1.377490     (-1.66261469102, -1.37749004179)
5 -0.154816  0.617671 -0.090484 -0.191906  (-0.0904840623396, -0.191905582481)
6 -0.705177 -1.086138 -0.629708  1.332853     (-0.629707821728, 1.33285348929)
7  0.637496 -0.643773 -0.492668 -0.777344   (-0.492667604075, -0.777344111021)
8  1.109497 -0.610165  0.260325  2.533383        (0.26032456699, 2.5333825651)
9 -1.224584  0.117668  1.304369 -0.152561     (1.30436900612, -0.152560909725)

Це геніально. Дякую. Очевидно, що я маю голову навколо лямбда-функцій.
elksie5000

Це працювало на ваших даних? Якщо так, чи можете ви поділитися своєю версією панди та даними? Цікаво, чому ваш код не працював, так і повинен.
Wouter Overmeire

Версія 0.10.1_20130131. Вибачте моє незнання, але який найкращий спосіб завантаження розділу даних для вас? (Ще відносний новачок).
elksie5000

Не вдалося відтворити 0.10.1. Найкращий спосіб завантаження? Ви можете або створити код, який генерує кадр, що містить випадкові дані, який має ту саму проблему, і поділитися цим кодом, або забрати кадр вище (зразок) та перенести його за допомогою безкоштовної служби передачі великих файлів. Як маринувати (в два рядки, без ","): імпортувати соління, з відкритим ("sample.pickle", "w") як файл: pickle.dump (зразок, файл)
Wouter Overmeire

1
Я спровокував це, оскільки мені потрібно застебнути 10 стовпців і не хочу давати ім'я даних фрейму 10 разів. Просто хочу дати назви стовпців.
rishi jain


3

Я хотів би додати df.values.tolist(). (доки ви не заперечуєте отримати стовпчик списків, а не кортежі)

import pandas as pd
import numpy as np

size = int(1e+07)
df = pd.DataFrame({'a': np.random.rand(size), 'b': np.random.rand(size)}) 

%timeit df.values.tolist()
1.47 s ± 38.9 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

%timeit list(zip(df.a,df.b))
1.92 s ± 131 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

Якщо у вас є більше , ніж тільки ці дві колонки: %timeit df[['a', 'b']].values.tolist(). Це все ще набагато швидше.
ChaimG
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.