Pandalar'da iki sütundan tuple sütunu nasıl oluşturulur


125

Pandas DataFrame'im var ve bir demet oluşturmak için 'enlem' ve 'uzun' sütunları birleştirmek istiyorum.

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

Kullanmaya çalıştığım kod şuydu:

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

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

Ancak bu, aşağıdaki hatayı döndürdü:

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

Bu sorunu nasıl çözebilirim?

Yanıtlar:


201

Rahat olun zip. Sütun verileriyle uğraşırken kullanışlıdır.

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

applyVeya kullanmaktan daha az karmaşık ve daha hızlı map. Gibi bir np.dstackşey iki kat daha hızlıdır zip, ancak size tekil vermez.


3
python3'te kullanmanız gerekir list. Bu işe df['new_col'] = list(zip(df.lat, df.long))
yaramalı

@paulwasit ah evet, aşkım python 3'ün tembel davranışıyla ilişkiden nefret ediyor. Teşekkürler.
Dale Jung

4
list(zip(df.lat, df.long))124 ms'deki bu yöntem , 900 bin df[['lat', 'long']].apply(tuple, axis=1)satırlar için 14,2 saniyeden çok daha etkilidir . Oran 100'den fazla.
Pengju Zhao

1
Bunu daha uzun bir sütun listesiyle kullanmaya çalışıyorum, df['new_col'] = list(zip(df[cols_to_keep])) ancak bir hata almaya devam ediyorum: Length of values does not match length of indexherhangi bir tavsiye?
seeiespi

1
@ PeterHansen'in cevabı bana yardımcı oldu, ancak önce listeyi açmak için * eksik olabileceğini düşünüyorum - yani 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)

Bu harika. Teşekkür ederim. Açıkça lambda fonksiyonlarına kafa yormam gerekiyor.
elksie5000

Bu verilerinizde işe yaradı mı? Öyleyse, panda sürümünüzü ve verilerinizi paylaşabilir misiniz? Kodunuzun neden çalışmadığını merak ediyorum, işe yaramalı.
Wouter Overmeire

Sürüm 0.10.1_20130131'dir. Cehaletimi bağışlayın, ancak sizin için bir veri bölümünü yüklemenin en iyi yolu nedir? (Hala göreceli bir acemi).
elksie5000

0.10.1'de yeniden üretemedim. Yüklemenin en iyi yolu? Rastgele verileri tutan bir çerçeve oluşturan, aynı sorunu olan ve bu kodu paylaşan bir kod oluşturabilir veya yukarıdaki çerçeveyi seçip (örnek) ücretsiz bir büyük dosya aktarım hizmeti aracılığıyla aktarabilirsiniz. Turşu nasıl yapılır (iki satırda, "," olmadan): turşu içe aktarın, dosya olarak açık ('sample.pickle', 'w') ile: pickle.dump (örnek, dosya)
Wouter Overmeire

1
Bunu 10 sütunu sıkıştırmam gerektiğinden ve 10 kez veri çerçevesi adı vermek istemediğim için oy verdim. Sadece Sütun isimleri vermek istiyorum.
rishi jain

13

Pandaların itertuplestam olarak bunu yapmak için bir yöntemi vardır :

list(df[['lat', 'long']].itertuples(index=False, name=None))

3

Eklemek istiyorum df.values.tolist(). (tuple yerine bir liste sütunu almayı düşünmediğiniz sürece)

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)

Sadece bu iki sütundaki daha var zaman: %timeit df[['a', 'b']].values.tolist(). Hala çok daha hızlı.
ChaimG
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.