Cách tạo cột tuple từ hai cột trong Pandas


125

Tôi có một Pandas DataFrame và tôi muốn kết hợp cột 'vĩ độ' và 'cột dài' để tạo thành một bộ.

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

Mã tôi đã cố gắng sử dụng là:

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

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

Tuy nhiên, điều này trả lại lỗi sau:

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

Làm thế nào tôi có thể giải quyết vấn đề này?

Câu trả lời:


201

Hãy thoải mái với zip. Nó có ích khi xử lý dữ liệu cột.

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

Nó ít phức tạp và nhanh hơn so với sử dụng applyhoặc map. Một cái gì đó giống np.dstacknhư nhanh hơn gấp đôi zip, nhưng sẽ không cung cấp cho bạn bộ giá trị.


3
trong python3, bạn phải sử dụng list. Điều này sẽ hoạt động:df['new_col'] = list(zip(df.lat, df.long))
paulwasit

@paulwasit à vâng, mối quan hệ yêu ghét của tôi với hành vi lười biếng của python 3. cảm ơn.
Dale Jung

4
Phương pháp này list(zip(df.lat, df.long))trong 124ms hiệu quả hơn nhiều so với df[['lat', 'long']].apply(tuple, axis=1)trong 14,2 giây cho 900k hàng. Tỷ lệ là hơn 100.
Pengju Zhao

1
Tôi đang cố gắng sử dụng điều này với một danh sách các cột dài hơn df['new_col'] = list(zip(df[cols_to_keep])) nhưng vẫn gặp lỗi: Length of values does not match length of indexbất kỳ lời khuyên nào?
seeiespi

1
Câu trả lời của @ PeterHansen đã giúp tôi nhưng nghĩ rằng có thể đã thiếu dấu * để giải nén danh sách trước - tức là 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)

Thật tuyệt. Cảm ơn bạn. Rõ ràng là tôi cần phải hiểu các hàm lambda.
elksie5000

Điều này có hoạt động trên dữ liệu của bạn không? Nếu vậy, bạn có thể chia sẻ phiên bản gấu trúc của mình và dữ liệu không? Tôi tự hỏi tại sao mã của bạn không hoạt động, nó phải.
Wouter Overmeire

Phiên bản là 0.10.1_20130131. Xin lỗi vì sự thiếu hiểu biết của tôi, nhưng cách tốt nhất để tải lên một phần dữ liệu cho bạn là gì? (Vẫn là một người mới tương đối).
elksie5000

Tôi không thể tạo lại trên 0.10.1. Cách tốt nhất để tải lên? Bạn có thể tạo mã tạo khung chứa dữ liệu ngẫu nhiên, có cùng vấn đề và chia sẻ mã đó hoặc chọn khung ở trên (mẫu) và chuyển nó qua dịch vụ truyền tệp lớn miễn phí. Làm thế nào để dưa (trong hai dòng, không có ""): dưa nhập khẩu, với mở ( 'sample.pickle', 'w') như file: pickle.dump (mẫu, tập tin)
Wouter Overmeire

1
Tôi đã ủng hộ cái này vì tôi cần nén 10 cột và không muốn đặt tên khung dữ liệu 10 lần. Chỉ muốn đặt tên Cột.
rishi jain

13

Pandas có itertuplesphương pháp để thực hiện chính xác điều này:

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

3

Tôi muốn thêm df.values.tolist(). (miễn là bạn không ngại lấy một cột danh sách thay vì các bộ giá trị)

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)

Khi bạn có nhiều hơn chỉ là hai cột này: %timeit df[['a', 'b']].values.tolist(). Nó vẫn nhanh hơn nhiều.
ChaimG
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.