web-dev-qa-db-ja.com

パンダDataFrameから列を削除します

DataFrameの列を削除するときに使用します。

del df['column_name']

そしてこれはうまくいきます。次のものが使えないのはなぜですか?

del df.column_name

df.column_nameとして/ Series列にアクセスできるので、これはうまくいくと期待しています。

914
John

Pythonの構文上の制限の結果としてdel df.column_nameを単純に機能させることは困難です。 del df[name]はPythonのカバーの下でdf.__delitem__(name)に翻訳されます。

512
Wes McKinney

パンダでこれをする最も良い方法は drop を使うことです:

df = df.drop('column_name', 1)

1 axis の数です(行の場合は0、列の場合は1

dfを再割り当てせずに列を削除するには、次のようにします。

df.drop('column_name', axis=1, inplace=True)

最後に、column label ではなくcolumn number でドロップするには、これを削除してみてください。 1、2、4列目:

df = df.drop(df.columns[[0, 1, 3]], axis=1)  # df.columns is zero-based pd.Index 
1681
LondonRob

つかいます:

columns = ['Col1', 'Col2', ...]
df.drop(columns, inplace=True, axis=1)

これにより、1つ以上の列がインプレースで削除されます。 inplace=Trueは、パンダv0.13で追加されたため、古いバージョンでは動作しません。その場合は、結果を元に戻す必要があります。

df = df.drop(columns, axis=1)
194
Krishna Sankar

インデックスでドロップ

1列目、2列目、4列目を削除します。

df.drop(df.columns[[0,1,3]], axis=1, inplace=True)

最初の列を削除します。

df.drop(df.columns[[0]], axis=1, inplace=True)

コピーを作成せずに元のデータを変更できるように、オプションのパラメータinplaceがあります。

ポップ

列の選択、追加、削除

column-nameを削除します。

df.pop('column-name')

例:

df = DataFrame.from_items([('A', [1, 2, 3]), ('B', [4, 5, 6]), ('C', [7,8, 9])], orient='index', columns=['one', 'two', 'three'])

print df

   one  two  three
A    1    2      3
B    4    5      6
C    7    8      9

df.drop(df.columns[[0]], axis=1, inplace=True)print df

   two  three
A    2      3
B    5      6
C    8      9

three = df.pop('three')print df

   two
A    2
B    5
C    8
90
jezrael

ここに提示される実際の質問は、ほとんどの回答で見逃されています。

del df.column_nameを使用できないのはなぜですか?

最初に、問題を理解する必要があります。そのためには、 python magic methods に飛び込む必要があります。

Wesが彼の答えで指摘しているように、del df['column']はpython magic methoddf.__delitem__('column')にマップされます。これは pandasで実装され、列

ただし、上記のリンクで指摘されている python magic methods

実際、delは、呼び出される不安定な状況のため、ほとんど使用すべきではありません。注意して使用してください!

del df['column_name']を使用したり、推奨したりすることはできません。したがって、del df.column_nameを考慮することすらすべきではありません。

ただし、理論的には、 マジックメソッドdel df.column_name を使用して、__delattr__をpandasで動作するように実装できます。ただし、これにより、特定の問題、del df['column_name']実装に既に存在する問題が発生しますが、程度は低くなります。

問題の例

「dtypes」または「columns」と呼ばれるデータフレームに列を定義するとどうなりますか。

次に、これらの列を削除するとします。

del df.dtypesは、「dtypes」属性または「dtypes」列を削除する必要があるかのように__delattr__メソッドを混乱させます。

この問題の背後にある建築上の質問

  1. データフレームはcolumnsのコレクションですか?
  2. データフレームはrowsのコレクションですか?
  3. 列はデータフレームのattributeですか?

パンダの答え:

  1. はい、すべての点で
  2. いいえ。ただし、必要に応じて、.ix.loc、または.ilocメソッドを使用できます。
  3. 多分、read dataにしたいですか?次に、yesnless属性の名前は、データフレームに属する別の属性によってすでに取得されています。 modify dataにしますか?次にno

TLDR;

pandasのアーキテクチャは非常に大きく成長しているため、この種の認知的不協和音がユーザーに発生しないようにするために再検討する必要があるため、del df.column_nameを実行できません。

アドバイス:

Df.column_nameを使用しないでください。かなりきれいかもしれませんが、認知的不協和音を引き起こします。

ここに収まるPython引用符の禅:

列を削除する方法は複数あります。

明白な方法が1つあり、できれば1つだけにする必要があります。

列は属性である場合もありますが、そうでない場合もあります。

特別なケースは、規則を破るほど特別ではありません。

del df.dtypesはdtypes属性またはdtypes列を削除しますか?

あいまいさに直面して、推測する誘惑を拒否します。

63
firelynx

Nice追加は、存在する場合にのみ 列を削除する能力です 。これにより、より多くのユースケースをカバーでき、渡されたラベルから既存の列のみが削除されます。

単純に errors = 'ignore' を追加するだけです。

df.drop(['col_name_1', 'col_name_2', ..., 'col_name_N'], inplace=True, axis=1, errors='ignore')
  • これはパンダ0.16.1以降から新しいです。ドキュメントは ここ です。
45
eiTan LaVi

バージョン0.16.1からあなたができる 

df.drop(['column_name'], axis = 1, inplace = True, errors = 'ignore')
39
sushmit

常に[]表記法を使用することをお勧めします。 1つの理由は、属性表記法(df.column_name)が番号付きインデックスに対して機能しないことです。

In [1]: df = DataFrame([[1, 2, 3], [4, 5, 6]])

In [2]: df[1]
Out[2]:
0    2
1    5
Name: 1

In [3]: df.1
  File "<ipython-input-3-e4803c0d1066>", line 1
    df.1
       ^
SyntaxError: invalid syntax
26
Andy Hayden

パンダ0.16.1以降では、@ eiTanLaViによって投稿されたソリューションごとに存在する場合にのみ列を削除できます。そのバージョンより前では、条件付きリスト内包表記を使って同じ結果を得ることができます。

df.drop([col for col in ['col_name_1','col_name_2',...,'col_name_N'] if col in df], 
        axis=1, inplace=True)
20
Alexander

パンダ0.21 +回答

Pandasバージョン0.21では、dropおよびindexメソッドのシグニチャと一致するように、columnsおよびrenameパラメータの両方を含めるように reindex メソッドが若干変更されました。 

df.drop(columns=['column_a', 'column_c'])

個人的には、列またはインデックスを表すのにaxisパラメータを使用することをお勧めします。これは、ほとんどすべてのパンダメソッドで使用されている主要なキーワードパラメータだからです。しかし、今、あなたはバージョン0.21でいくつかの追加の選択肢があります。

15
Ted Petrou

TL、DR

わずかに効率的な解決策を見つけるための多大な努力。 df.drop(dlst, 1, errors='ignore')の単純さを犠牲にしながら、追加された複雑さを正当化することは困難です

df.reindex_axis(np.setdiff1d(df.columns.values, dlst), 1)

プリアンブル
列を削除することは、他の列を選択することと意味的に同じです。考慮すべきいくつかの追加の方法を示します。 

また、一度に複数の列を削除して、存在しない列を削除する試みを許可するという一般的な解決策にも焦点を当てます。 

これらの解決策を使用するのは一般的であり、単純な場合にも同様に機能します。


セットアップ
pd.DataFramedfおよびリストを考慮して削除しますdlst

df = pd.DataFrame(dict(Zip('ABCDEFGHIJ', range(1, 11))), range(3))
dlst = list('HIJKLM')

df

   A  B  C  D  E  F  G  H  I   J
0  1  2  3  4  5  6  7  8  9  10
1  1  2  3  4  5  6  7  8  9  10
2  1  2  3  4  5  6  7  8  9  10

dlst

['H', 'I', 'J', 'K', 'L', 'M']

結果は次のようになります。

df.drop(dlst, 1, errors='ignore')

   A  B  C  D  E  F  G
0  1  2  3  4  5  6  7
1  1  2  3  4  5  6  7
2  1  2  3  4  5  6  7

列を削除することを他の列を選択することと同じなので、2つのタイプに分けます。

  1. ラベル選択
  2. ブール選択

ラベル選択

削除したい列を除いて、残したい列を表すラベルのリスト/配列を作ることから始めます。

  1. df.columns.difference(dlst)

    Index(['A', 'B', 'C', 'D', 'E', 'F', 'G'], dtype='object')
    
  2. np.setdiff1d(df.columns.values, dlst)

    array(['A', 'B', 'C', 'D', 'E', 'F', 'G'], dtype=object)
    
  3. df.columns.drop(dlst, errors='ignore')

    Index(['A', 'B', 'C', 'D', 'E', 'F', 'G'], dtype='object')
    
  4. list(set(df.columns.values.tolist()).difference(dlst))

    # does not preserve order
    ['E', 'D', 'B', 'F', 'G', 'A', 'C']
    
  5. [x for x in df.columns.values.tolist() if x not in dlst]

    ['A', 'B', 'C', 'D', 'E', 'F', 'G']
    

ラベルからの列
選択プロセスを比較するために、次のように仮定します。

 cols = [x for x in df.columns.values.tolist() if x not in dlst]

それから私達は評価してもいいです 

  1. df.loc[:, cols]
  2. df[cols]
  3. df.reindex(columns=cols)
  4. df.reindex_axis(cols, 1)

どれがすべてに評価されます:

   A  B  C  D  E  F  G
0  1  2  3  4  5  6  7
1  1  2  3  4  5  6  7
2  1  2  3  4  5  6  7

ブールスライス

スライス用のブール値の配列/リストを作成できます。

  1. ~df.columns.isin(dlst)
  2. ~np.in1d(df.columns.values, dlst)
  3. [x not in dlst for x in df.columns.values.tolist()]
  4. (df.columns.values[:, None] != dlst).all(1)

ブール値の列
比較のために 

bools = [x not in dlst for x in df.columns.values.tolist()]
  1. df.loc[: bools]

どれがすべてに評価されます:

   A  B  C  D  E  F  G
0  1  2  3  4  5  6  7
1  1  2  3  4  5  6  7
2  1  2  3  4  5  6  7

堅牢なタイミング  

関数 

setdiff1d = lambda df, dlst: np.setdiff1d(df.columns.values, dlst)
difference = lambda df, dlst: df.columns.difference(dlst)
columndrop = lambda df, dlst: df.columns.drop(dlst, errors='ignore')
setdifflst = lambda df, dlst: list(set(df.columns.values.tolist()).difference(dlst))
comprehension = lambda df, dlst: [x for x in df.columns.values.tolist() if x not in dlst]

loc = lambda df, cols: df.loc[:, cols]
slc = lambda df, cols: df[cols]
ridx = lambda df, cols: df.reindex(columns=cols)
ridxa = lambda df, cols: df.reindex_axis(cols, 1)

isin = lambda df, dlst: ~df.columns.isin(dlst)
in1d = lambda df, dlst: ~np.in1d(df.columns.values, dlst)
comp = lambda df, dlst: [x not in dlst for x in df.columns.values.tolist()]
brod = lambda df, dlst: (df.columns.values[:, None] != dlst).all(1)

テスト  

res1 = pd.DataFrame(
    index=pd.MultiIndex.from_product([
        'loc slc ridx ridxa'.split(),
        'setdiff1d difference columndrop setdifflst comprehension'.split(),
    ], names=['Select', 'Label']),
    columns=[10, 30, 100, 300, 1000],
    dtype=float
)

res2 = pd.DataFrame(
    index=pd.MultiIndex.from_product([
        'loc'.split(),
        'isin in1d comp brod'.split(),
    ], names=['Select', 'Label']),
    columns=[10, 30, 100, 300, 1000],
    dtype=float
)

res = res1.append(res2).sort_index()

dres = pd.Series(index=res.columns, name='drop')

for j in res.columns:
    dlst = list(range(j))
    cols = list(range(j // 2, j + j // 2))
    d = pd.DataFrame(1, range(10), cols)
    dres.at[j] = timeit('d.drop(dlst, 1, errors="ignore")', 'from __main__ import d, dlst', number=100)
    for s, l in res.index:
        stmt = '{}(d, {}(d, dlst))'.format(s, l)
        setp = 'from __main__ import d, dlst, {}, {}'.format(s, l)
        res.at[(s, l), j] = timeit(stmt, setp, number=100)

rs = res / dres

rs

                          10        30        100       300        1000
Select Label                                                           
loc    brod           0.747373  0.861979  0.891144  1.284235   3.872157
       columndrop     1.193983  1.292843  1.396841  1.484429   1.335733
       comp           0.802036  0.732326  1.149397  3.473283  25.565922
       comprehension  1.463503  1.568395  1.866441  4.421639  26.552276
       difference     1.413010  1.460863  1.587594  1.568571   1.569735
       in1d           0.818502  0.844374  0.994093  1.042360   1.076255
       isin           1.008874  0.879706  1.021712  1.001119   0.964327
       setdiff1d      1.352828  1.274061  1.483380  1.459986   1.466575
       setdifflst     1.233332  1.444521  1.714199  1.797241   1.876425
ridx   columndrop     0.903013  0.832814  0.949234  0.976366   0.982888
       comprehension  0.777445  0.827151  1.108028  3.473164  25.528879
       difference     1.086859  1.081396  1.293132  1.173044   1.237613
       setdiff1d      0.946009  0.873169  0.900185  0.908194   1.036124
       setdifflst     0.732964  0.823218  0.819748  0.990315   1.050910
ridxa  columndrop     0.835254  0.774701  0.907105  0.908006   0.932754
       comprehension  0.697749  0.762556  1.215225  3.510226  25.041832
       difference     1.055099  1.010208  1.122005  1.119575   1.383065
       setdiff1d      0.760716  0.725386  0.849949  0.879425   0.946460
       setdifflst     0.710008  0.668108  0.778060  0.871766   0.939537
slc    columndrop     1.268191  1.521264  2.646687  1.919423   1.981091
       comprehension  0.856893  0.870365  1.290730  3.564219  26.208937
       difference     1.470095  1.747211  2.886581  2.254690   2.050536
       setdiff1d      1.098427  1.133476  1.466029  2.045965   3.123452
       setdifflst     0.833700  0.846652  1.013061  1.110352   1.287831

fig, axes = plt.subplots(2, 2, figsize=(8, 6), sharey=True)
for i, (n, g) in enumerate([(n, g.xs(n)) for n, g in rs.groupby('Select')]):
    ax = axes[i // 2, i % 2]
    g.plot.bar(ax=ax, title=n)
    ax.legend_.remove()
fig.tight_layout()

これはdf.drop(dlst, 1, errors='ignore')の実行にかかる時間と相対的です。それは結局のところ、我々はわずかにパフォーマンスを向上させるだけのように思えます。

enter image description here

実際のところ、最善の解決策はハックlist(set(df.columns.values.tolist()).difference(dlst))reindexまたはreindex_axisを使うことです。 dropよりもすぐ近くにあり、それでもごくわずかに優れているのはnp.setdiff1dです。

rs.idxmin().pipe(
    lambda x: pd.DataFrame(
        dict(idx=x.values, val=rs.lookup(x.values, x.index)),
        x.index
    )
)

                      idx       val
10     (ridx, setdifflst)  0.653431
30    (ridxa, setdifflst)  0.746143
100   (ridxa, setdifflst)  0.816207
300    (ridx, setdifflst)  0.780157
1000  (ridxa, setdifflst)  0.861622
11
piRSquared

データフレーム(df)から単一の列(col_name)を削除する場合は、次のいずれかを試してください。

df = df.drop(col_name, axis=1)

または 

df.drop(col_name, axis=1, inplace=True)

データフレーム(df)から列のリスト(col_lst = [col_name_1,col_name_2,...])を削除したい場合は、次のいずれかを試してください。

df.drop(col_lst, axis=1, inplace=True)

または 

df.drop(columns=col_lst, inplace=True)
7
Stephanie

ドット構文はJavaScriptでは機能しますが、Pythonでは機能しません。

  • Python:del df['column_name']
  • JavaScript:del df['column_name'] または del df.column_name
2
Doctor

複数のデータフレームから列を削除する

DataFrameのリストから(同じ名前を持つ)列を削除する方法に関する情報を探している場合は、いくつかの方法があります。

1つの方法は、リストを反復処理して各DataFrameをその場で変更することです。

# In-place assignment
for df in df_list:
    df.drop('colname', axis=1, inplace=True)

または、

for df in df_list: df.pop('colname')

または、列を(インプレースではなく)ドロップして結果をそのリスト位置に割り当てます。

# Reassigning a copy back to the list
for i, df in enumerate(df_list):
    df_list[i] = df.drop('colname', axis=1, inplace=True)

再現可能なコードサンプル

df1 = pd.DataFrame({'A': [1, 2, 3], 'B': [4, 5, 6]})
df2 = pd.DataFrame({'A': [4, 5, 7], 'C': ['a', 'b', 'c']})

df1
   A  B
0  1  4
1  2  5
2  3  6

df2
   A  C
0  4  a
1  5  b
2  7  c

df_list = [df1, df2]
# Drop column "A"
for df in df_list:
    df.drop('A', axis=1, inplace=True)

df1
   B
0  4
1  5
2  6

df2
   C
0  a
1  b
2  c

for df in df_list: df = df.drop('colname', axis=1)(つまり、ループ内での再割り当て)が機能しないのはなぜですか?

他の回答で述べたように、df.dropはデフォルトでコピーを返します。コピーは返され、元のものに変更を加えることなくvariabledfに再割り当てされます。 inplace=True引数を使用してdfをその場で変更するか、コピーをそのリスト要素に明示的に再割り当てする必要があります。


変数とオブジェクトの違いを理解することは重要です。変数はオブジェクトへの参照を保持します。変数は、異なるオブジェクトを参照するように再割り当てすることができます。これは、オブジェクト自体を変更することとは関係ありません。このトピックに関する良い入門書として、Ned Batchelderによる この記事を読むことをお勧めします。

1
cs95

これを試して、私はこれが最も簡単な方法だと思います:

drop((['A','B'],axis=1)

0
Aymen Alsaadi

Pandas DataFrameの列を削除する別の方法

インプレース削除を探していない場合は、DataFrame(...)関数を使用して列を指定して新しいDataFrameを作成できます。

my_dict = { 'name' : ['a','b','c','d'], 'age' : [10,20,25,22], 'designation' : ['CEO', 'VP', 'MD', 'CEO']}

df = pd.DataFrame(my_dict)

新しいDataFrameを作成します。

newdf = pd.DataFrame(df, columns=['name', 'age'])

Del/dropで得られるものと同じくらい良い結果が得られます

0
Daksh