วิธีสร้างคอลัมน์ทูเพิลจากสองคอลัมน์ใน 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))

มันซับซ้อนน้อยกว่าและเร็วกว่าการใช้หรือapply mapสิ่งที่ต้องการnp.dstackเร็วกว่าสองเท่าzipแต่จะไม่ให้สิ่งที่คุณเห็น


3
ใน python3 คุณต้องใช้list. สิ่งนี้ควรได้ผล:df['new_col'] = list(zip(df.lat, df.long))
paulwasit

@ paulwasit ใช่แล้วความรักของฉันเกลียดความสัมพันธ์กับพฤติกรรมขี้เกียจของ python 3 ขอบคุณ
Dale Jung

4
วิธีนี้list(zip(df.lat, df.long))ใน 124ms มีประสิทธิภาพมากกว่าdf[['lat', 'long']].apply(tuple, axis=1)ใน 14.2 วินาทีสำหรับ 900k แถว อัตราส่วนมากกว่า 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

สิ่งนี้ได้ผลกับข้อมูลของคุณหรือไม่ ถ้าเป็นเช่นนั้นคุณสามารถแบ่งปันเวอร์ชันแพนด้าและข้อมูลของคุณได้ไหม ฉันสงสัยว่าทำไมรหัสของคุณไม่ทำงานก็ควร
Wouter Overmeire

เวอร์ชันคือ 0.10.1_20130131 ขอโทษที่ฉันไม่รู้ แต่วิธีที่ดีที่สุดในการอัปโหลดส่วนข้อมูลสำหรับคุณคืออะไร (ยังเป็นญาติมือใหม่).
elksie5000

ฉันไม่สามารถสร้างซ้ำบน 0.10.1 วิธีที่ดีที่สุดในการอัปโหลด? คุณสามารถสร้างรหัสที่สร้างเฟรมที่เก็บข้อมูลแบบสุ่มที่มีปัญหาเดียวกันและแบ่งปันรหัสนั้นหรือเก็บกรอบด้านบน (ตัวอย่าง) และถ่ายโอนผ่านบริการถ่ายโอนไฟล์ขนาดใหญ่ฟรี วิธีการดอง (เป็นสองบรรทัดโดยไม่มี ","): นำเข้าผักดองโดยเปิด ('sample.pickle', 'w') เป็นไฟล์: pickle.dump (ตัวอย่าง, ไฟล์)
Wouter Overmeire

1
ฉันได้เพิ่มคะแนนสิ่งนี้แล้วเนื่องจากฉันต้องการ zip 10 คอลัมน์และไม่ต้องการให้ชื่อ dataframe 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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.