ย้ายคอลัมน์ตามชื่อไปด้านหน้าตารางในแพนด้า


97

นี่คือ df ของฉัน:

                             Net   Upper   Lower  Mid  Zsore
Answer option                                                
More than once a day          0%   0.22%  -0.12%   2    65 
Once a day                    0%   0.32%  -0.19%   3    45
Several times a week          2%   2.45%   1.10%   4    78
Once a week                   1%   1.63%  -0.40%   6    65

ฉันจะย้ายคอลัมน์โดยใช้ชื่อ ( "Mid") ไปที่ด้านหน้าของตารางดัชนี 0 ได้อย่างไรผลลัพธ์ควรมีลักษณะดังนี้:

                             Mid   Upper   Lower  Net  Zsore
Answer option                                                
More than once a day          2   0.22%  -0.12%   0%    65 
Once a day                    3   0.32%  -0.19%   0%    45
Several times a week          4   2.45%   1.10%   2%    78
Once a week                   6   1.63%  -0.40%   1%    65

รหัสปัจจุบันของฉันย้ายคอลัมน์ตามดัชนีโดยใช้df.columns.tolist()แต่ฉันต้องการเปลี่ยนตามชื่อ

คำตอบ:


114

เราสามารถใช้ixเรียงลำดับใหม่ได้โดยส่งผ่านรายการ:

In [27]:
# get a list of columns
cols = list(df)
# move the column to head of list using index, pop and insert
cols.insert(0, cols.pop(cols.index('Mid')))
cols
Out[27]:
['Mid', 'Net', 'Upper', 'Lower', 'Zsore']
In [28]:
# use ix to reorder
df = df.ix[:, cols]
df
Out[28]:
                      Mid Net  Upper   Lower  Zsore
Answer_option                                      
More_than_once_a_day    2  0%  0.22%  -0.12%     65
Once_a_day              3  0%  0.32%  -0.19%     45
Several_times_a_week    4  2%  2.45%   1.10%     78
Once_a_week             6  1%  1.63%  -0.40%     65

อีกวิธีหนึ่งคือการอ้างอิงคอลัมน์และใส่กลับเข้าไปใหม่ที่ด้านหน้า:

In [39]:
mid = df['Mid']
df.drop(labels=['Mid'], axis=1,inplace = True)
df.insert(0, 'Mid', mid)
df
Out[39]:
                      Mid Net  Upper   Lower  Zsore
Answer_option                                      
More_than_once_a_day    2  0%  0.22%  -0.12%     65
Once_a_day              3  0%  0.32%  -0.19%     45
Several_times_a_week    4  2%  2.45%   1.10%     78
Once_a_week             6  1%  1.63%  -0.40%     65

คุณยังสามารถใช้locเพื่อให้ได้ผลลัพธ์เช่นเดียวกับที่ixจะเลิกใช้งานในอนาคตของแพนด้าตั้งแต่0.20.0เป็นต้นไป:

df = df.loc[:, cols]

54

บางทีฉันอาจจะพลาดบางอย่างไป แต่คำตอบเหล่านี้ดูเหมือนซับซ้อนเกินไป คุณควรจะสามารถตั้งค่าคอลัมน์ภายในรายการเดียว:

คอลัมน์ด้านหน้า:

df = df[ ['Mid'] + [ col for col in df.columns if col != 'Mid' ] ]

หรือหากต้องการย้ายไปด้านหลัง:

df = df[ [ col for col in df.columns if col != 'Mid' ] + ['Mid'] ]

หรือถ้าคุณต้องการย้ายมากกว่าหนึ่งคอลัมน์:

cols_to_move = ['Mid', 'Zsore']
df           = df[ cols_to_move + [ col for col in df.columns if col not in cols_to_move ] ]

สำหรับคนอื่นตรวจสอบให้แน่ใจว่าคุณใช้คอลัมน์หลายคอลัมน์ตัวเลือกที่ 3 ตัวเลือกที่ 1 ที่มีหลายคอลัมน์จะไม่ลบMid& Zscoreออกจากคอลัมน์จากตำแหน่งเดิม ฉันพบสิ่งนี้โดยมีGrouperข้อผิดพลาดในการพยายามจัดกลุ่มเมื่อมีคอลัมน์เดียวกันสองครั้ง
the775

46

คุณสามารถใช้ฟังก์ชัน df.reindex () ในแพนด้าได้ df คือ

                      Net  Upper   Lower  Mid  Zsore
Answer option                                      
More than once a day  0%  0.22%  -0.12%    2     65
Once a day            0%  0.32%  -0.19%    3     45
Several times a week  2%  2.45%   1.10%    4     78
Once a week           1%  1.63%  -0.40%    6     65

กำหนดรายชื่อคอลัมน์

cols = df.columns.tolist()
cols
Out[13]: ['Net', 'Upper', 'Lower', 'Mid', 'Zsore']

ย้ายชื่อคอลัมน์ไปทุกที่ที่คุณต้องการ

cols.insert(0, cols.pop(cols.index('Mid')))
cols
Out[16]: ['Mid', 'Net', 'Upper', 'Lower', 'Zsore']

จากนั้นใช้df.reindex()ฟังก์ชันเพื่อจัดลำดับใหม่

df = df.reindex(columns= cols)

เอาท์พุทคือ: df

                      Mid  Upper   Lower Net  Zsore
Answer option                                      
More than once a day    2  0.22%  -0.12%  0%     65
Once a day              3  0.32%  -0.19%  0%     45
Several times a week    4  2.45%   1.10%  2%     78
Once a week             6  1.63%  -0.40%  1%     65

31

ฉันชอบวิธีนี้:

col = df.pop("Mid")
df.insert(0, col.name, col)

อ่านง่ายกว่าและเร็วกว่าคำตอบอื่น ๆ ที่แนะนำ

def move_column_inplace(df, col, pos):
    col = df.pop(col)
    df.insert(pos, col.name, col)

การประเมินประสิทธิภาพ:

สำหรับการทดสอบนี้คอลัมน์สุดท้ายในปัจจุบันจะถูกย้ายไปด้านหน้าในการทำซ้ำแต่ละครั้ง วิธีการในสถานที่โดยทั่วไปจะทำงานได้ดีกว่า ในขณะที่วิธีการแก้ปัญหาของ citynorman สามารถทำได้ในสถานที่ แต่วิธีการของ Ed Chum ตาม.locและวิธีการของ sachinnm ตามreindexไม่สามารถทำได้

ในขณะที่วิธีการอื่น ๆ เป็นวิธีการทั่วไป แต่โซลูชันของ citynorman จำกัดpos=0อยู่ที่ ฉันไม่ได้สังเกตความแตกต่างของประสิทธิภาพระหว่างdf.loc[cols]และdf[cols]ด้วยเหตุนี้ฉันจึงไม่ได้ให้คำแนะนำอื่น ๆ

ฉันทดสอบด้วย python 3.6.8 และแพนด้า 0.24.2 บน MacBook Pro (กลางปี ​​2015)

import numpy as np
import pandas as pd

n_cols = 11
df = pd.DataFrame(np.random.randn(200000, n_cols),
                  columns=range(n_cols))

def move_column_inplace(df, col, pos):
    col = df.pop(col)
    df.insert(pos, col.name, col)

def move_to_front_normanius_inplace(df, col):
    move_column_inplace(df, col, 0)
    return df

def move_to_front_chum(df, col):
    cols = list(df)
    cols.insert(0, cols.pop(cols.index(col)))
    return df.loc[:, cols]

def move_to_front_chum_inplace(df, col):
    col = df[col]
    df.drop(col.name, axis=1, inplace=True)
    df.insert(0, col.name, col)
    return df

def move_to_front_elpastor(df, col):
    cols = [col] + [ c for c in df.columns if c!=col ]
    return df[cols] # or df.loc[cols]

def move_to_front_sachinmm(df, col):
    cols = df.columns.tolist()
    cols.insert(0, cols.pop(cols.index(col)))
    df = df.reindex(columns=cols, copy=False)
    return df

def move_to_front_citynorman_inplace(df, col):
    # This approach exploits that reset_index() moves the index
    # at the first position of the data frame.
    df.set_index(col, inplace=True)
    df.reset_index(inplace=True)
    return df

def test(method, df):
    col = np.random.randint(0, n_cols)
    method(df, col)

col = np.random.randint(0, n_cols)
ret_mine = move_to_front_normanius_inplace(df.copy(), col)
ret_chum1 = move_to_front_chum(df.copy(), col)
ret_chum2 = move_to_front_chum_inplace(df.copy(), col)
ret_elpas = move_to_front_elpastor(df.copy(), col)
ret_sach = move_to_front_sachinmm(df.copy(), col)
ret_city = move_to_front_citynorman_inplace(df.copy(), col)

# Assert equivalence of solutions.
assert(ret_mine.equals(ret_chum1))
assert(ret_mine.equals(ret_chum2))
assert(ret_mine.equals(ret_elpas))
assert(ret_mine.equals(ret_sach))
assert(ret_mine.equals(ret_city))

ผลลัพธ์ :

# For n_cols = 11:
%timeit test(move_to_front_normanius_inplace, df)
# 1.05 ms ± 42.4 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
%timeit test(move_to_front_citynorman_inplace, df)
# 1.68 ms ± 46.1 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
%timeit test(move_to_front_sachinmm, df)
# 3.24 ms ± 96.5 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit test(move_to_front_chum, df)
# 3.84 ms ± 114 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit test(move_to_front_elpastor, df)
# 3.85 ms ± 58.3 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit test(move_to_front_chum_inplace, df)
# 9.67 ms ± 101 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)


# For n_cols = 31:
%timeit test(move_to_front_normanius_inplace, df)
# 1.26 ms ± 31.6 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit test(move_to_front_citynorman_inplace, df)
# 1.95 ms ± 260 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit test(move_to_front_sachinmm, df)
# 10.7 ms ± 348 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit test(move_to_front_chum, df)
# 11.5 ms ± 869 µs per loop (mean ± std. dev. of 7 runs, 100 loops each
%timeit test(move_to_front_elpastor, df)
# 11.4 ms ± 598 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit test(move_to_front_chum_inplace, df)
# 31.4 ms ± 1.89 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

2
ทางออกที่ดี อย่างไรก็ตามเราไม่ควรกำหนด df ที่แก้ไขด้วยคอลัมน์แทรกให้กับ df ดั้งเดิมอย่างชัดเจน ดังนั้นแทนที่จะเราต้องทำdf = df.insert(0, col.name, col) df.insert(0, col.name, col)คุณมีอย่างถูกต้องในฟังก์ชั่นmove_column_inplace()แม้ว่า
melihozbek

1
ขอบคุณ @normanius ฉันทำงานอย่างหนักในห้องปฏิบัติการของเด็กซ์เตอร์ :-) ทางออกที่ดี มีดโกนของ Occam เรียบง่ายและสง่างาม
brohjoe

ฉันชอบโซลูชันนี้ด้วย :)
user88484

19

ฉันไม่ชอบวิธีที่ฉันต้องระบุคอลัมน์อื่น ๆ ทั้งหมดอย่างชัดเจนในโซลูชันอื่น ๆ ดังนั้นสิ่งนี้จึงเหมาะกับฉันมากที่สุด แม้ว่าอาจจะช้าสำหรับดาต้าเฟรมขนาดใหญ่ ... ?

df = df.set_index('Mid').reset_index()


สิ่งนี้ใช้ประโยชน์จากการreset_index()แทรกดัชนีที่ลดลงที่ตำแหน่งแรกในเวอร์ชันปัจจุบัน แต่โปรดทราบว่าพฤติกรรมนี้ไม่ได้ระบุไว้ในเอกสาร
normanius

1
สำหรับประสิทธิภาพดูคำตอบของฉัน เป็นประโยชน์ที่จะใช้inplace=Trueสำหรับทั้งสองset_index()และreset_index().
normanius

9

นี่คือชุดรหัสทั่วไปที่ฉันมักใช้เพื่อจัดเรียงตำแหน่งของคอลัมน์ใหม่ คุณอาจพบว่ามีประโยชน์

cols = df.columns.tolist()
n = int(cols.index('Mid'))
cols = [cols[n]] + cols[:n] + cols[n+1:]
df = df[cols]

3
ควรอธิบายคำตอบของคุณและสิ่งที่ทำให้เป็นทางออกที่ดีและไม่เพียง แต่โพสต์โค้ดเท่านั้น คุณกำลังเสี่ยงที่จะลง
คะแนนเสียง

5

ในการจัดลำดับแถวของ DataFrame ใหม่ให้ใช้รายการดังต่อไปนี้

df = df[['Mid', 'Net', 'Upper', 'Lower', 'Zsore']]

สิ่งนี้ทำให้เห็นได้ชัดว่าเกิดอะไรขึ้นเมื่ออ่านโค้ดในภายหลัง ยังใช้:

df.columns
Out[1]: Index(['Net', 'Upper', 'Lower', 'Mid', 'Zsore'], dtype='object')

จากนั้นตัดและวางเพื่อจัดลำดับใหม่


สำหรับ DataFrame ที่มีคอลัมน์จำนวนมากให้จัดเก็บรายการคอลัมน์ในตัวแปรและแสดงคอลัมน์ที่ต้องการไว้ด้านหน้ารายการ นี่คือตัวอย่าง:

cols = [str(col_name) for col_name in range(1001)]
data = np.random.rand(10,1001)
df = pd.DataFrame(data=data, columns=cols)

mv_col = cols.pop(cols.index('77'))
df = df[[mv_col] + cols]

ตอนนี้df.columnsมี.

Index(['77', '0', '1', '2', '3', '4', '5', '6', '7', '8',
       ...
       '991', '992', '993', '994', '995', '996', '997', '998', '999', '1000'],
      dtype='object', length=1001)

จะเกิดอะไรขึ้นถ้าคุณทำงานกับ DataFrame ที่ประกอบด้วย 1001 คอลัมน์
normanius

แนวคิดนี้เหมือนกัน แต่ด้วยคอลัมน์จำนวนมากควรจัดเก็บคอลัมน์ไว้ในรายการและควรจัดการรายการ ดูตัวอย่างการแก้ไขของฉันด้านบน ตัวอย่างของฉันได้อย่างมีประสิทธิภาพเช่นเดียวกับstackoverflow.com/a/51009742/5827921
Dustin Helliwell

1

นี่คือคำตอบที่ง่ายมากสำหรับสิ่งนี้

อย่าลืมเครื่องหมายวงเล็บ (()) สองอันรอบชื่อคอลัมน์มิฉะนั้นจะทำให้คุณมีข้อผิดพลาด


# here you can add below line and it should work 
df = df[list(('Mid','Upper', 'Lower', 'Net','Zsore'))]
df

                             Mid   Upper   Lower  Net  Zsore
Answer option                                                
More than once a day          2   0.22%  -0.12%   0%    65 
Once a day                    3   0.32%  -0.19%   0%    45
Several times a week          4   2.45%   1.10%   2%    78
Once a week                   6   1.63%  -0.40%   1%    65

เห็นได้ชัดว่า OP ไม่ต้องการสะกดชื่อคอลัมน์อย่างชัดเจน ในบางกรณีที่มีดาต้าเฟรมกว้างมากอาจทำไม่ได้ด้วยซ้ำ
Ledger Yu

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.