パンダのデータフレームで複数の列を選択する


1113

別の列にデータがありますが、それを抽出して別の変数に保存する方法がわかりません。

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

どのように私は選択しない'a''b'とDF1にそれを保存しますか?

私は試した

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

どれも動作しないようです。


2
.ix曖昧なので使いたくない。.ilocまたは必要に.loc応じて使用します。
Acumenus 2017

1
ヘッダー名を参照せずに実行できる方法はありますか?Rのように、次のように実行できます。これ> csvtable_imp_1 <- csvtable_imp[0:6]により、最初の列のデルタ量が0から6の間で選択されます。必要なのは、読み取りライブラリーで区切られたcsv-tableを読み取ることだけです。
MichaelR 2018年

もう少し作業しました。思い通りに機能するものを見つけました。デフォルトでは、列ではなく文字数を選択します。infile_1 = largefile_stay.ix[:,0:6]
MichaelR 2018年

3
この後半でつまずく人のために、ixは非推奨になりました。パンダは、loc(ラベルベースのインデックス)またはiloc(位置ベースのインデックス)のいずれかを使用することをお勧めします。
ZaydH 2018

回答:


1770

列名(文字列)は、試した方法ではスライスできません。

ここにはいくつかのオプションがあります。コンテキストからどの変数を切り出したいかがわかっている場合は、__getitem__構文([])にリストを渡して、それらの列のみのビューを返すことができます。

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

または、名前ではなく数値でそれらにインデックスを付けることが重要な場合(たとえば、コードは最初の2つの列の名前を知らなくても自動的にこれを行う必要がある)、代わりにこれを行うことができます。

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

さらに、Pandasオブジェクトのビューではなく、そのオブジェクトのコピーのビューを理解する必要があります。上記のメソッドの最初のメソッドは、目的のサブオブジェクト(目的のスライス)のメモリに新しいコピーを返します。

ただし、これを行わず、元のオブジェクトのサブオブジェクトまたはスライスと同じメモリチャンクを参照するだけの新しい変数がPandaにある場合があります。これはインデックス作成の2番目の方法で発生するため、copy()関数で変更して通常のコピーを取得できます。この場合、スライスされたオブジェクトであると考えるものを変更すると、元のオブジェクトが変更されることがあります。いつもこれに気をつけてください。

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

を使用ilocするには、列の位置(またはインデックス)を知っている必要があります。列の位置が変わる可能性があるため、インデックスをハードコーディングする代わりに、データフレームオブジェクトのメソッドの関数ilocと共に使用して、列のインデックスを取得できます。get_loccolumns

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

これで、このディクショナリを使用して、名前とを使用して列にアクセスできますiloc


192
注:df[['a','b']]コピーを作成します
ウェスマッキーニー

1
はい、これは私の答えに含まれていました。コピーについてのビットはix[]、あなたが何らかの理由で使用したい場合にのみ使用ix[]するためのものでした。
12

1
ix列ではなく行にインデックスを付けます。OPは列が必要だと思いました。
ホブ、

9
ixスライス引数を受け入れるため、列を取得することもできます。たとえばdf.ix[0:2, 0:2]、NumPy行列の場合と同様に、左上の2x2サブ配列を取得します(もちろん、列名によって異なります)。のように、列の文字列名にスライス構文を使用することもできますdf.ix[0, 'Col1':'Col5']。それは起こるすべての列が間を注文するために取得Col1し、Col5中にdf.columns配列。がix行にインデックスを付けると言うのは誤りです。これが最も基本的な使用法です。それよりもはるかに多くのインデックス作成をサポートします。したがって、ixこの質問には完全に一般的です。
2012年

7
@AndrewCassidy .ixを再び使用しないでください。整数でスライスしたい場合.ilocは、Pythonリストのように最後の位置を除いて使用します。
Ted Petrou 2017

133

バージョン0.11.0以降では、インデクサーを使用して試した方法で列スライスできます.loc

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

同等です

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

からまでの列Cを返しますE


ランダムに生成されたDataFrameのデモ:

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

列をCからEに取得するには(整数スライスとは異なり、列に「E」が含まれていることに注意してください):

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

ラベルに基づいて行を選択する場合も同様です。これらの列から「R6」から「R10」までの行を取得します。

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

.locまた、ブール配列を受け入れるため、配列内の対応するエントリがである列を選択できますTrue。たとえば、列名がリストにある場合は-Trueをdf.columns.isin(list('BCD'))返します。そうでなければ、偽。array([False, True, True, True, False, False], dtype=bool)['B', 'C', 'D']

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

列名(df.columns)が['index','a','b','c']であるとすると、必要なデータは3番目と4番目の列にあります。スクリプトの実行時にそれらの名前がわからない場合は、これを行うことができます

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

EMSが彼の回答で指摘しているようにdf.ix列をもう少し簡潔に.columnsスライスしますが、スライスインターフェイスは、バニラ1-D Pythonリストのインデックス付け/スライス構文を使用するため、より自然なものになる可能性があります。

警告:列の'index'名前としては不適切ですDataFrame。同じラベルが実際のdf.index属性であるIndex配列にも使用されます。したがって、列はによって返されdf['index']、実際のDataFrameインデックスはによって返されdf.indexます。Indexは、そのSeries要素の値を検索するために最適化された特別な種類です。df.indexの場合、ラベルで行を検索するためのものです。そのdf.columns属性はpd.Index、ラベルで列を検索するための配列でもあります。


3
上記のコメントで述べたように、行だけで.ixはありません。汎用スライシング用で、多次元スライシングに使用できます。基本的には、NumPyの通常の__getitem__構文へのインターフェースにすぎません。つまり、転置操作を適用するだけで、列スライスの問題を行スライスの問題に簡単に変換できますdf.T。あなたの例columns[1:3]では、少し誤解を招くを使用しています。の結果はcolumnsですSeries。配列のように扱わないように注意してください。また、columns[2:3]「3番目と4番目」のコメントと一致するように変更する必要があります。
2012年

@ Mr.F:私[2:4]は正しいです。あなた[2:3]は間違っています。また、標準のPythonスライシング表記を使用してシーケンス/シリーズを生成しても、IMOを誤解させることはありません。しかし、DataFrameインターフェイスをバイパスして、基になるnumpy配列にでアクセスするのが好きixです。
2016

あなたはこの場合正しいですが、私が試みていたポイントは、一般的に、パンダでラベルを使ってスライスすることは、スライスエンドポイントを含むことです(または、少なくともこれは、以前のほとんどのパンダバージョンの動作でした)。したがって、取得df.columnsてラベルでスライスする場合、整数のインデックス位置でスライスする場合とは異なるスライスのセマンティクスが得られます。私は前のコメントでもそれをうまく説明していませんでした。
2016

ああ、今私はあなたのポイントを理解しています。それcolumnsが不変のシリーズであることを忘れており、ゲッターはラベルをインデックスとして使用するようにオーバーライドされています。明確にするために時間を割いていただきありがとうございます。
ホブ2016

2
非推奨の警告に注意してください:.ixは非推奨です。したがって、これは理にかなっています。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
私はのような例を何かのために、列の名前を変更したい場合:df[['b as foo', 'c as bar']出力は、列の名前を変更するようなb通りfooやコラムcなどbar
kuanb 2017

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

62

この質問はかなり古いですが、パンダの最新バージョンでは、これを正確に行う簡単な方法があります。列名(文字列)、好きな方法でスライスできます。

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

6
これは作成時にのみ実行できます。問題は、それをデータフレームにすでに持っているかどうかを尋ねることです。
Banjocat 2017年

3
@Banjocat、それは既存のデータフレームで動作します
mhery

23

ドロップする列のリストを提供drop()し、Pandas DataFrameの関数を使用して、必要な列のみを含むDataFrameを返すことができます。

ただ言って

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

bとだけのDataFrameを返しますc

dropこの方法は、文書化されてここに


23

パンダと一緒に、

ウィット列名

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

ilocとインデックス番号を持つ特定の列で選択するには:

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

locカラム名は次のように使用できます

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

20

この方法は非常に便利であることがわかりました。

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

詳細はこちら


たとえば、2列目と5列目だけをどう思いますか?
324

1
それはその時でしょうsurveys_df.iloc [:, [2,5]]
ジュリアンゴーファー

15

0.21.0以降では、ラベルが欠落している1つ以上のリストを使用する.loc[]、リストとともに使用することは非推奨になりました.reindex。だから、あなたの質問への答えは:

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

以前のバージョンでは、.loc[list-of-labels]少なくとも1つのキーが見つかった場合に限り使用できました(そうでない場合はが発生しましたKeyError)。この動作は廃止され、警告メッセージが表示されるようになりました。推奨される代替手段はを使用すること.reindex()です。

データのインデックス作成と選択で詳細を読む


10

パンダが使えます。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'])

データフレーム:

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

1つ以上の列を名前で選択するには:

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

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

次のものも使用できます。

    df.Test_2

そして、列を取得します Test_2

    Jane     2
    Peter    4
    Alex     7
    Ann      6

を使用して、これらの行から列と行を選択することもできます.loc()。これは「スライス」と呼ばれます。列Test_1からTest_3

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

「スライス」は:

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

そして、あなたが望むだけPeterAnn、列Test_1とからTest_3

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

あなたが得る:

           Test_1  Test_3
    Peter       5       5
    Ann         7       9

8

行インデックスと列名で1つの要素を取得する場合は、のように実行できますdf['b'][0]。想像するのと同じくらい簡単です。

またはdf.ix[0,'b']、インデックスとラベルを組み合わせて使用​​することもできます。

注: v0.20以降ixloc/ が代わりに廃止されましたiloc


6

1つの異なる簡単なアプローチ:行の反復

iterowsの使用

 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
iterrows()の使用はお勧めしません。それはパンダの歴史の中で最悪のアンチパターンの露骨なイネーブラーです。
cs95

「最悪のアンチパターン」とはどういう意味ですか?
アンキタ

1
私見、パンダを使用するときはiterrows()が最後のオプションであるべきです。
Elf、

5

上記の応答で説明されているさまざまなアプローチは、ユーザーがドロップまたはサブセット化する列インデックスを知っているか、列の範囲を使用してデータフレームをサブセット化することを想定している(たとえば、「C」:「E」の間) 。pandas.DataFrame.dropは、() (あなたは常にデータフレームとのコピーを使用することを慎重にする必要がありけれども、確かにユーザーによって定義された列のリストに基づいて、サブセットデータにオプションでインプレースのパラメータをに設定すべきではない本当 !!)

別のオプションは、列名に設定された違いを実行し、目的の列を含む配列のインデックスタイプを返すpandas.columns.difference()を使用することです。以下は解決策です:

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)

出力は次のようになります。 b c 1 3 4 2 4 5


1
copy()は必要ありません。つまりdf1 = df[df.columns.difference(columns_for_differencing)]、新しい/コピーされたデータフレームを返します。変更df1せずに変更できdfます。ありがとう、ところで。これはまさに私が必要としたものでした。
Bazyli Debowski

4

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

これが役立つ場合は、df.pop(c)を使用してください


3

私はそれについていくつかの答えを見てきましたが、私にはわかりませんでした。関心のある列をどのように選択しますか?その答えは、それらをリストに集めた場合、リストを使用して列を参照するだけでよいということです。

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

extracted_features63列を指定する次のリスト/ numpy配列があります。元のデータセットには10​​3列あり、それらを正確に抽出したいので、

dataset[extracted_features]

そして、あなたはこれで終わります

ここに画像の説明を入力してください

これは、機械学習で(より具体的には、機能選択で)よく使用するものです。他の方法についても説明したいと思いますが、それはすでに他のスタックオーバーフラワーでカバーされていると思います。これがお役に立てば幸いです!


2

pandas.DataFrame.filterメソッドを使用して、次のように列をフィルタリングまたは並べ替えることができます。

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
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.