Pandas의 두 열에서 튜플 열을 형성하는 방법


125

Pandas DataFrame이 있고 '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))

그것은 덜 복잡하고 빠르게 사용하는 것보다 것 applymap. 같은 np.dstack것은.보다 두 배 빠르지 zip만 튜플을 제공하지는 않습니다.


3
python3에서는 list. 작동해야합니다.df['new_col'] = list(zip(df.lat, df.long))
paulwasit

@paulwasit 아 예, 내 사랑은 파이썬 3의 게으른 행동과의 관계를 싫어합니다. 감사.
Dale Jung

4
list(zip(df.lat, df.long))124ms 의이 방법 은 df[['lat', 'long']].apply(tuple, axis=1)900k 행에 대해 14.2 초 보다 훨씬 효율적 입니다. 비율은 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 2013

버전은 0.10.1_20130131입니다. 실례합니다. 데이터 섹션을 업로드하는 가장 좋은 방법은 무엇입니까? (아직 상대적인 초보자).
elksie5000 2013

0.10.1에서 재현하지 못했습니다. 업로드하는 가장 좋은 방법은? 동일한 문제가있는 임의의 데이터를 보유하는 프레임을 생성하는 코드를 생성하고 해당 코드를 공유하거나 위의 프레임 (샘플)을 선택하여 무료 대용량 파일 전송 서비스를 통해 전송할 수 있습니다. 방법 ( ","없이, 두 줄) 피클합니다 : 수입 피클을 오픈과 함께 ( 'sample.pickle', 'W') 파일로 : pickle.dump (샘플 파일)
WOUTER Overmeire

1
10 개의 열을 압축해야하고 데이터 프레임 이름을 10 번 제공하고 싶지 않기 때문에 이것을 upvoted했습니다. 열 이름을 지정하고 싶습니다.
리시 자이나교


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
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.