Chọn nhiều cột trong khung dữ liệu gấu trúc


1113

Tôi có dữ liệu trong các cột khác nhau nhưng tôi không biết cách trích xuất nó để lưu nó vào một biến khác.

index  a   b   c
1      2   3   4
2      3   4   5

Làm thế nào để chọn 'a', 'b'và lưu nó vào df1?

Tôi đã thử

df1 = df['a':'b']
df1 = df.ix[:, 'a':'b']

Không có vẻ gì để làm việc.


2
Bạn không bao giờ muốn sử dụng .ixvì nó mơ hồ. Sử dụng .ilochoặc .locnếu bạn phải.
Acumenus

1
Có cách nào có thể được thực hiện mà không cần tham khảo tên tiêu đề? Giống như trong R, tôi có thể làm như thế này: > csvtable_imp_1 <- csvtable_imp[0:6]và nó chọn số lượng delta của các cột đầu tiên trong khoảng từ 0 đến 6. Tất cả những gì tôi phải làm là đọc bảng csv như được phân định bằng libr đọc.
MichaelR

Tôi đã làm việc nhiều hơn một chút với nó. Tìm thấy một cái gì đó làm việc như mong muốn. Mặc định là chọn số char và không phải cột. infile_1 = largefile_stay.ix[:,0:6]
MichaelR

3
Đối với những người vấp ngã vào cuối này, ixbây giờ bị phản đối. Pandas khuyên bạn nên sử dụng: loc(lập chỉ mục dựa trên nhãn) hoặc iloc(lập chỉ mục dựa trên vị trí).
ZaydH

Câu trả lời:


1769

Tên cột (là chuỗi) không thể được cắt theo cách bạn đã thử.

Ở đây bạn có một vài lựa chọn. Nếu bạn biết từ ngữ cảnh mà biến bạn muốn cắt ra, bạn chỉ có thể trả về chế độ xem chỉ các cột đó bằng cách chuyển danh sách vào __getitem__cú pháp ([] 's).

df1 = df[['a','b']]

Ngoài ra, nếu việc lập chỉ mục số và không theo tên của họ là quan trọng (giả sử mã của bạn sẽ tự động làm điều này mà không cần biết tên của hai cột đầu tiên) thì bạn có thể thực hiện việc này thay thế:

df1 = df.iloc[:,0:2] # Remember that Python does not slice inclusive of the ending index.

Ngoài ra, bạn nên tự làm quen với ý tưởng về chế độ xem vào đối tượng Pandas so với bản sao của đối tượng đó. Các phương thức đầu tiên ở trên sẽ trả về một bản sao mới trong bộ nhớ của đối tượng con mong muốn (các lát mong muốn).

Tuy nhiên, đôi khi, có các quy ước lập chỉ mục trong Pandas không thực hiện điều này và thay vào đó cung cấp cho bạn một biến mới chỉ đề cập đến cùng một đoạn bộ nhớ là đối tượng phụ hoặc lát cắt trong đối tượng ban đầu. Điều này sẽ xảy ra với cách lập chỉ mục thứ hai, vì vậy bạn có thể sửa đổi nó với copy()chức năng để có được một bản sao thông thường. Khi điều này xảy ra, việc thay đổi những gì bạn nghĩ là đối tượng bị cắt đôi khi có thể thay đổi đối tượng ban đầu. Luôn luôn tốt để được nhìn ra cho điều này.

df1 = df.iloc[0,0:2].copy() # To avoid the case where changing df1 also changes df

Để sử dụng iloc, bạn cần biết các vị trí cột (hoặc chỉ mục). Vì các vị trí cột có thể thay đổi, thay vì các chỉ mục mã hóa cứng, bạn có thể sử dụng iloccùng với get_locchức năng của columnsphương thức của đối tượng dataframe để lấy các chỉ mục cột.

{df.columns.get_loc(c):c for idx, c in enumerate(df.columns)}

Bây giờ bạn có thể sử dụng từ điển này để truy cập các cột thông qua tên và sử dụng iloc.


192
Lưu ý: df[['a','b']]tạo bản sao
Wes McKinney

1
Vâng, điều này đã được ngầm định trong câu trả lời của tôi. Một chút về bản sao chỉ được sử dụng ix[]nếu bạn thích sử dụng ix[]vì bất kỳ lý do gì.
ely

1
ixlập chỉ mục hàng, không phải cột. Tôi nghĩ rằng OP muốn cột.
hobs

9
ixchấp nhận đối số lát, vì vậy bạn cũng có thể nhận được các cột. Ví dụ, df.ix[0:2, 0:2]lấy mảng con 2x2 phía trên bên trái giống như đối với ma trận NumPy (tùy thuộc vào tên cột của khóa học). Bạn thậm chí có thể sử dụng cú pháp lát trên tên chuỗi của các cột, như df.ix[0, 'Col1':'Col5']. Điều đó có được tất cả các cột xảy ra để được sắp xếp giữa Col1Col5trong df.columnsmảng. Không đúng khi nói rằng ixcác chỉ mục hàng. Đó chỉ là cách sử dụng cơ bản nhất của nó. Nó cũng hỗ trợ lập chỉ mục nhiều hơn thế. Vì vậy, ixlà hoàn toàn chung cho câu hỏi này.
ely

7
@AndrewCassidy Không bao giờ sử dụng .ix nữa. Nếu bạn muốn cắt với số nguyên, hãy sử dụng .ilocvị trí cuối cùng giống như danh sách Python.
Ted Petrou

133

Kể từ phiên bản 0.11.0, các cột có thể được cắt theo cách bạn đã thử bằng cách sử dụng bộ .locchỉ mục:

df.loc[:, 'C':'E']

tương đương với

df[['C', 'D', 'E']]  # or df.loc[:, ['C', 'D', 'E']]

và trả về các cột Cthông qua E.


Bản trình diễn trên DataFrame được tạo ngẫu nhiên:

import pandas as pd
import numpy as np
np.random.seed(5)
df = pd.DataFrame(np.random.randint(100, size=(100, 6)), 
                  columns=list('ABCDEF'), 
                  index=['R{}'.format(i) for i in range(100)])
df.head()

Out: 
     A   B   C   D   E   F
R0  99  78  61  16  73   8
R1  62  27  30  80   7  76
R2  15  53  80  27  44  77
R3  75  65  47  30  84  86
R4  18   9  41  62   1  82

Để lấy các cột từ C đến E (lưu ý rằng không giống như cắt số nguyên, 'E' được bao gồm trong các cột):

df.loc[:, 'C':'E']

Out: 
      C   D   E
R0   61  16  73
R1   30  80   7
R2   80  27  44
R3   47  30  84
R4   41  62   1
R5    5  58   0
...

Công việc tương tự để chọn hàng dựa trên nhãn. Nhận các hàng 'R6' đến 'R10' từ các cột đó:

df.loc['R6':'R10', 'C':'E']

Out: 
      C   D   E
R6   51  27  31
R7   83  19  18
R8   11  67  65
R9   78  27  29
R10   7  16  94

.loccũng chấp nhận một mảng boolean để bạn có thể chọn các cột có mục tương ứng trong mảng là True. Ví dụ: df.columns.isin(list('BCD'))trả về array([False, True, True, True, False, False], dtype=bool)- Đúng nếu tên cột có trong danh sách ['B', 'C', 'D']; Sai, nếu không.

df.loc[:, df.columns.isin(list('BCD'))]

Out: 
      B   C   D
R0   78  61  16
R1   27  30  80
R2   53  80  27
R3   65  47  30
R4    9  41  62
R5   78   5  58
...

110

Giả sử tên cột của bạn là ( df.columns) ['index','a','b','c'], thì dữ liệu bạn muốn nằm trong cột thứ 3 & 4. Nếu bạn không biết tên của họ khi tập lệnh của bạn chạy, bạn có thể làm điều này

newdf = df[df.columns[2:4]] # Remember, Python is 0-offset! The "3rd" entry is at slot 2.

Như EMS chỉ ra trong câu trả lời của mình , df.ixcác lát cắt chính xác hơn một chút, nhưng .columnsgiao diện cắt có thể tự nhiên hơn vì nó sử dụng cú pháp lập chỉ mục / cắt xén danh sách python 1-D.

WARN: 'index'là một tên xấu cho một DataFramecột. Nhãn tương tự cũng được sử dụng cho df.indexthuộc tính thực , một Indexmảng. Vì vậy, cột của bạn được trả về bởi df['index']và chỉ mục DataFrame thực được trả về df.index. An Indexlà một loại đặc biệt được Seriestối ưu hóa để tra cứu các giá trị của các phần tử. Đối với df.index, đó là tìm kiếm các hàng theo nhãn của họ. df.columnsThuộc tính đó cũng là một pd.Indexmảng, để tìm kiếm các cột theo nhãn của chúng.


3
Như tôi đã nêu trong bình luận của tôi ở trên, .ixkhông chỉ dành riêng cho dòng. Nó được sử dụng cho mục đích chung, và có thể được sử dụng để cắt đa chiều. Về cơ bản, đây chỉ là một giao diện theo __getitem__cú pháp thông thường của NumPy . Điều đó nói rằng, bạn có thể dễ dàng chuyển đổi một vấn đề cắt cột thành vấn đề cắt hàng bằng cách chỉ áp dụng một hoạt động chuyển vị , df.T. Ví dụ của bạn sử dụng columns[1:3], đó là một chút sai lệch. Kết quả columnslà a Series; hãy cẩn thận không chỉ coi nó như một mảng. Ngoài ra, có lẽ bạn nên thay đổi nó columns[2:3]để phù hợp với nhận xét "thứ 3 & thứ 4" của bạn.
ely

@ Mr.F: Tôi [2:4]đúng. Bạn [2:3]sai rồi Và sử dụng ký hiệu cắt trăn tiêu chuẩn để tạo chuỗi / Sê-ri không gây hiểu lầm cho IMO. Nhưng tôi thích việc bạn bỏ qua giao diện DataFrame để truy cập vào mảng numpy cơ bản với ix.
hobs

Bạn đã đúng trong trường hợp này, nhưng điểm tôi đã cố gắng đưa ra là nói chung, việc cắt lát với nhãn trong Pandas bao gồm điểm cuối lát cắt (hoặc ít nhất đây là hành vi trong hầu hết các phiên bản Pandas trước đó). Vì vậy, nếu bạn truy xuất df.columnsvà muốn cắt nó theo nhãn , thì bạn sẽ có ngữ nghĩa lát khác với khi bạn cắt nó theo vị trí chỉ số nguyên . Tôi chắc chắn đã không giải thích nó tốt trong bình luận trước đây của tôi.
ely

Ahh, bây giờ tôi thấy quan điểm của bạn. Tôi quên rằng đó columnslà một Series bất biến và getter đã bị ghi đè để sử dụng nhãn làm chỉ số. Cảm ơn đã dành thời gian để làm rõ.
hobs

2
Lưu ý Cảnh báo khấu hao: .ix không dùng nữa. Do đó, điều này có ý nghĩa: newdf = df [df.columns [2: 4]]
Martien Lubberink

64
In [39]: df
Out[39]: 
   index  a  b  c
0      1  2  3  4
1      2  3  4  5

In [40]: df1 = df[['b', 'c']]

In [41]: df1
Out[41]: 
   b  c
0  3  4
1  4  5

1
Điều gì sẽ xảy ra nếu tôi muốn đổi tên cột, ví dụ như: df[['b as foo', 'c as bar']ví dụ như đầu ra đổi tên cột bthành foovà cột cbar?
kuanb

5
df[['b', 'c']].rename(columns = {'b' : 'foo', 'c' : 'bar'})
Greg

62

Tôi nhận ra câu hỏi này khá cũ, nhưng trong phiên bản mới nhất của gấu trúc có một cách dễ dàng để làm chính xác điều này. Tên cột (là chuỗi) có thể được cắt theo bất cứ cách nào bạn muốn.

columns = ['b', 'c']
df1 = pd.DataFrame(df, columns=columns)

6
Điều này chỉ có thể được thực hiện trên sáng tạo. Câu hỏi là hỏi bạn đã có nó trong một khung dữ liệu chưa.
Banjocat

3
@Banjocat, nó hoạt động với một khung dữ liệu hiện có
vào

23

Bạn có thể cung cấp danh sách các cột được loại bỏ và trả lại DataFrame chỉ với các cột cần thiết bằng cách sử dụng drop()chức năng trên Pandas DataFrame.

Chỉ nói

colsToDrop = ['a']
df.drop(colsToDrop, axis=1)

sẽ trả về một DataFrame chỉ với các cột bc.

Các dropphương pháp được ghi lại ở đây .


23

Với gấu trúc,

tên cột dí dỏm

dataframe[['column1','column2']]

để chọn theo iloc và các cột cụ thể với số chỉ mục:

dataframe.iloc[:,[1,2]]

với tên cột loc có thể được sử dụng như

dataframe.loc[:,['column1','column2']]

20

Tôi thấy phương pháp này rất hữu ích:

# iloc[row slicing, column slicing]
surveys_df.iloc [0:3, 1:4]

Thông tin chi tiết có thể được tìm thấy ở đây


Làm thế nào bạn sẽ lấy, chỉ, cột 2 và 5?
324

1
Đó sẽ là surveys_df.iloc [:, [2,5]]sau đó.
Julian Gorfer

15

Bắt đầu với 0.21.0, việc sử dụng .lochoặc []với một danh sách có một hoặc nhiều nhãn bị thiếu sẽ không được chấp nhận .reindex. Vì vậy, câu trả lời cho câu hỏi của bạn là:

df1 = df.reindex(columns=['b','c'])

Trong các phiên bản trước, việc sử dụng .loc[list-of-labels]sẽ hoạt động miễn là tìm thấy ít nhất 1 phím (nếu không nó sẽ tăng a KeyError). Hành vi này không được chấp nhận và hiện hiển thị thông báo cảnh báo. Thay thế được đề nghị là sử dụng .reindex().

Đọc thêm tại Lập chỉ mục và chọn dữ liệu


10

Bạn có thể sử dụng gấu trúc. Tôi tạo DataFrame:

    import pandas as pd
    df = pd.DataFrame([[1, 2,5], [5,4, 5], [7,7, 8], [7,6,9]], 
                      index=['Jane', 'Peter','Alex','Ann'],
                      columns=['Test_1', 'Test_2', 'Test_3'])

Khung dữ liệu:

           Test_1  Test_2  Test_3
    Jane        1       2       5
    Peter       5       4       5
    Alex        7       7       8
    Ann         7       6       9

Để chọn 1 hoặc nhiều cột theo tên:

    df[['Test_1','Test_3']]

           Test_1  Test_3
    Jane        1       5
    Peter       5       5
    Alex        7       8
    Ann         7       9

Bạn cũng có thể dùng:

    df.Test_2

Và bạn nhận được cột Test_2

    Jane     2
    Peter    4
    Alex     7
    Ann      6

Bạn cũng có thể chọn các cột và hàng từ các hàng này bằng cách sử dụng .loc(). Điều này được gọi là "cắt" . Lưu ý rằng tôi lấy từ cột Test_1đếnTest_3

    df.loc[:,'Test_1':'Test_3']

"Lát" là:

            Test_1  Test_2  Test_3
     Jane        1       2       5
     Peter       5       4       5
     Alex        7       7       8
     Ann         7       6       9

Và nếu bạn chỉ muốn PeterAnntừ các cột Test_1Test_3:

    df.loc[['Peter', 'Ann'],['Test_1','Test_3']]

Bạn lấy:

           Test_1  Test_3
    Peter       5       5
    Ann         7       9

8

Nếu bạn muốn lấy một phần tử theo chỉ mục hàng và tên cột, bạn có thể làm điều đó giống như df['b'][0]. Nó là đơn giản như bạn có thể hình ảnh.

Hoặc bạn có thể sử dụng df.ix[0,'b'], sử dụng hỗn hợp chỉ mục và nhãn.

Lưu ý: Vì v0.20 ixđã bị từ chối ủng hộ loc/ iloc.


6

Một cách tiếp cận khác nhau và dễ dàng: lặp hàng

sử dụng lặp

 df1= pd.DataFrame() #creating an empty dataframe
 for index,i in df.iterrows():
    df1.loc[index,'A']=df.loc[index,'A']
    df1.loc[index,'B']=df.loc[index,'B']
    df1.head()

5
Vui lòng không khuyến nghị sử dụng iterrows (). Nó là một kẻ gây ra trắng trợn về kiểu chống tệ hại nhất trong lịch sử gấu trúc.
cs95

Bạn có thể vui lòng giải thích ý của bạn về "chống mẫu tồi tệ nhất" không?
Ankita

1
IMHO, iterrows () nên là lựa chọn cuối cùng khi sử dụng gấu trúc.
Yêu tinh

5

Các cách tiếp cận khác nhau được thảo luận trong các phản hồi ở trên dựa trên giả định rằng người dùng biết các chỉ số của cột để thả hoặc tập hợp con hoặc người dùng muốn tập hợp một khung dữ liệu bằng cách sử dụng một phạm vi cột (ví dụ giữa 'C': 'E') . pandas.DataFrame.drop () chắc chắn là một lựa chọn số liệu tập hợp con dựa trên một danh sách các cột được định nghĩa bởi người sử dụng (mặc dù bạn phải thận trọng mà bạn luôn luôn sử dụng bản sao của dataframe và inplace thông số không nên được đặt thành Đúng !!)

Một tùy chọn khác là sử dụng pandas.columns.difference () , thực hiện một sự khác biệt được đặt trên các tên cột và trả về một loại chỉ mục của mảng chứa các cột mong muốn. Sau đây là giải pháp:

df = pd.DataFrame([[2,3,4],[3,4,5]],columns=['a','b','c'],index=[1,2])
columns_for_differencing = ['a']
df1 = df.copy()[df.columns.difference(columns_for_differencing)]
print(df1)

Đầu ra sẽ là: b c 1 3 4 2 4 5


1
Bản sao () là không cần thiết. tức là: df1 = df[df.columns.difference(columns_for_differencing)]sẽ trả về một khung dữ liệu mới / được sao chép. Bạn sẽ có thể sửa đổi df1mà không cần thay đổi df. Cảm ơn bạn, btw. Đây chính xác là những gì tôi cần.
Bazyli Debowski

4

bạn cũng có thể sử dụng df.pop ()

>>> df = pd.DataFrame([('falcon', 'bird',    389.0),
...                    ('parrot', 'bird',     24.0),
...                    ('lion',   'mammal',   80.5),
...                    ('monkey', 'mammal', np.nan)],
...                   columns=('name', 'class', 'max_speed'))
>>> df
     name   class  max_speed
0  falcon    bird      389.0
1  parrot    bird       24.0
2    lion  mammal       80.5
3  monkey  mammal 

>>> df.pop('class')
0      bird
1      bird
2    mammal
3    mammal
Name: class, dtype: object

>>> df
     name  max_speed
0  falcon      389.0
1  parrot       24.0
2    lion       80.5
3  monkey        NaN

cho tôi biết nếu điều này có ích cho bạn, vui lòng sử dụng df.pop (c)


3

Tôi đã thấy một số câu trả lời về điều đó, nhưng vẫn chưa rõ ràng với tôi. Làm thế nào bạn sẽ chọn những cột quan tâm? Câu trả lời là nếu bạn tập hợp chúng trong một danh sách, bạn chỉ có thể tham chiếu các cột bằng danh sách.

Thí dụ

print(extracted_features.shape)
print(extracted_features)

(63,)
['f000004' 'f000005' 'f000006' 'f000014' 'f000039' 'f000040' 'f000043'
 'f000047' 'f000048' 'f000049' 'f000050' 'f000051' 'f000052' 'f000053'
 'f000054' 'f000055' 'f000056' 'f000057' 'f000058' 'f000059' 'f000060'
 'f000061' 'f000062' 'f000063' 'f000064' 'f000065' 'f000066' 'f000067'
 'f000068' 'f000069' 'f000070' 'f000071' 'f000072' 'f000073' 'f000074'
 'f000075' 'f000076' 'f000077' 'f000078' 'f000079' 'f000080' 'f000081'
 'f000082' 'f000083' 'f000084' 'f000085' 'f000086' 'f000087' 'f000088'
 'f000089' 'f000090' 'f000091' 'f000092' 'f000093' 'f000094' 'f000095'
 'f000096' 'f000097' 'f000098' 'f000099' 'f000100' 'f000101' 'f000103']

Tôi có danh sách / mảng numpy sau extracted_features, chỉ định 63 cột. Tập dữ liệu gốc có 103 cột và tôi muốn trích xuất chính xác những cột đó, sau đó tôi sẽ sử dụng

dataset[extracted_features]

Và bạn sẽ kết thúc với điều này

nhập mô tả hình ảnh ở đây

Đây là thứ bạn sẽ sử dụng khá thường xuyên trong Machine Learning (cụ thể hơn là trong lựa chọn tính năng). Tôi cũng muốn thảo luận về những cách khác, nhưng tôi nghĩ rằng điều đó đã được bao phủ bởi các stackoverflowers khác. Hy vọng điều này đã có ích!


2

Bạn có thể sử dụng pandas.DataFrame.filterphương thức để lọc hoặc sắp xếp lại các cột như thế này:

df1 = df.filter(['a', 'b'])

0
df[['a','b']] # select all rows of 'a' and 'b'column 
df.loc[0:10, ['a','b']] # index 0 to 10 select column 'a' and 'b'
df.loc[0:10, ['a':'b']] # index 0 to 10 select column 'a' to 'b'
df.iloc[0:10, 3:5] # index 0 to 10 and column 3 to 5
df.iloc[3, 3:5] # index 3 of column 3 to 5
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.