Как сформировать столбец кортежа из двух столбцов в Pandas


126

У меня есть 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 

Как я могу решить эту проблему?

Ответы:


202

Привыкайте к себе 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

@paulwasit ах да, моя любовь ненавижу отношения с ленивым поведением python 3. Спасибо.
Дейл Юнг,

4
Этот метод list(zip(df.lat, df.long))за 124 мс намного эффективнее, чем df[['lat', 'long']].apply(tuple, axis=1)за 14,2 с для 900 тыс. Строк. Соотношение больше 100.
Pengju Zhao

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

1
@ Ответ PeterHansen помог мне , но думаю , что это может быть пропущен * распаковывать список первой - то есть 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

Это сработало с вашими данными? Если да, можете ли вы поделиться своей версией pandas и данными? Интересно, почему ваш код не работал, так и должно быть.
Wouter Overmeire

Версия - 0.10.1_20130131. Извините за мое незнание, но как лучше всего загрузить раздел данных для вас? (Все еще относительный новичок).
elksie5000

На 0.10.1 воспроизвести не удалось. Лучший способ загрузки? Вы можете либо создать код, который генерирует фрейм, содержащий случайные данные, которые имеют ту же проблему, и поделиться этим кодом, либо выбрать фрейм выше (образец) и передать его через бесплатную службу передачи больших файлов. Как мариновать (в две строки, без ","): импортировать рассол с open ('sample.pickle', 'w') как файл: pickle.dump (sample, file)
Воутер Овермайр

1
Я проголосовал за это, так как мне нужно заархивировать 10 столбцов, и я не хочу 10 раз указывать имя фрейма данных. Просто хочу дать имена столбцам.
риши джайн


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.