pandasDataFrameから空のセルを含む行を削除します


92

私はpd.DataFrameいくつかのExcelスプレッドシートを解析することによって作成されたものを持っています。その列のセルは空です。たとえば、以下はその列の頻度の出力です。32320レコードにはテナントの値がありません。

>>> value_counts(Tenant, normalize=False)
                              32320
    Thunderhead                8170
    Big Data Others            5700
    Cloud Cruiser              5700
    Partnerpedia               5700
    Comcast                    5700
    SDP                        5700
    Agora                      5700
    dtype: int64

テナントが欠落している行を削除しようとし.isnull()ていますが、オプションが欠落している値を認識しません。

>>> df['Tenant'].isnull().sum()
    0

列のデータ型は「オブジェクト」です。この場合はどうなりますか?テナントが欠落しているレコードをドロップするにはどうすればよいですか?

回答:


179

Pandasは、値がオブジェクトの場合、値をnullとして認識し、DataFrameのnp.nanようNaNに出力します。欠落している値はおそらく空の文字列であり、Pandasはこれをnullとして認識しません。これを修正するには、を使用して空の刺し傷(または空のセルにあるもの)をnp.nanオブジェクトに変換してから、DataFrameをreplace()呼び出しdropna()てテナントがnullの行を削除します。

実例を示すために、列にいくつかのランダムな値といくつかの空の文字列を含むDataFrameを作成しTenantsます。

>>> import pandas as pd
>>> import numpy as np
>>> 
>>> df = pd.DataFrame(np.random.randn(10, 2), columns=list('AB'))
>>> df['Tenant'] = np.random.choice(['Babar', 'Rataxes', ''], 10)
>>> print df

          A         B   Tenant
0 -0.588412 -1.179306    Babar
1 -0.008562  0.725239         
2  0.282146  0.421721  Rataxes
3  0.627611 -0.661126    Babar
4  0.805304 -0.834214         
5 -0.514568  1.890647    Babar
6 -1.188436  0.294792  Rataxes
7  1.471766 -0.267807    Babar
8 -1.730745  1.358165  Rataxes
9  0.066946  0.375640         

次に、Tenants列内の空の文字列を次のnp.nanようにオブジェクトに置き換えます。

>>> df['Tenant'].replace('', np.nan, inplace=True)
>>> print df

          A         B   Tenant
0 -0.588412 -1.179306    Babar
1 -0.008562  0.725239      NaN
2  0.282146  0.421721  Rataxes
3  0.627611 -0.661126    Babar
4  0.805304 -0.834214      NaN
5 -0.514568  1.890647    Babar
6 -1.188436  0.294792  Rataxes
7  1.471766 -0.267807    Babar
8 -1.730745  1.358165  Rataxes
9  0.066946  0.375640      NaN

これで、null値を削除できます。

>>> df.dropna(subset=['Tenant'], inplace=True)
>>> print df

          A         B   Tenant
0 -0.588412 -1.179306    Babar
2  0.282146  0.421721  Rataxes
3  0.627611 -0.661126    Babar
5 -0.514568  1.890647    Babar
6 -1.188436  0.294792  Rataxes
7  1.471766 -0.267807    Babar
8 -1.730745  1.358165  Rataxes

どうもありがとうございました。これを試して戻ってきます!
Amrita Sawant 2015年

2
@mcmath、少し好奇心が強い。なぜnumpyをインポートして、できるのに使用np.nanするのですpd.np.nanか?
propjk007 2015

3
@ propjk007、人生の多くのことと同様に、多くのことを行う方法はたくさんあります
andrew 2017

私からのテスト、それはやっているようだdf[df['Tenant'].astype(bool)]が- (唯一の空の文字列をなし空白文字を想定していない)より速くよりdf.replace('', np.nan).dropna(subset=['Tenant'])
cs95

53

Pythonic + Pandorable: df[df['col'].astype(bool)]

空の文字列は偽物です。つまり、次のようにブール値でフィルタリングできます。

df = pd.DataFrame({
    'A': range(5),
    'B': ['foo', '', 'bar', '', 'xyz']
})
df
   A    B
0  0  foo
1  1     
2  2  bar
3  3     
4  4  xyz
df['B'].astype(bool)                                                                                                                      
0     True
1    False
2     True
3    False
4     True
Name: B, dtype: bool

df[df['B'].astype(bool)]                                                                                                                  
   A    B
0  0  foo
2  2  bar
4  4  xyz

空の文字列だけでなく、空白のみを含む文字列も削除することが目標である場合は、str.strip事前に次を使用してください。

df[df['B'].str.strip().astype(bool)]
   A    B
0  0  foo
2  2  bar
4  4  xyz

思ったより速い

.astypeはベクトル化された操作であり、これはこれまでに提示されたすべてのオプションよりも高速です。少なくとも、私のテストから。YMMV。

これがタイミングの比較です、私が考えることができる他のいくつかの方法を投入しました。

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

参考のためのベンチマークコード:

import pandas as pd
import perfplot

df1 = pd.DataFrame({
    'A': range(5),
    'B': ['foo', '', 'bar', '', 'xyz']
})

perfplot.show(
    setup=lambda n: pd.concat([df1] * n, ignore_index=True),
    kernels=[
        lambda df: df[df['B'].astype(bool)],
        lambda df: df[df['B'] != ''],
        lambda df: df[df['B'].replace('', np.nan).notna()],  # optimized 1-col
        lambda df: df.replace({'B': {'': np.nan}}).dropna(subset=['B']),  
    ],
    labels=['astype', "!= ''", "replace + notna", "replace + dropna", ],
    n_range=[2**k for k in range(1, 15)],
    xlabel='N',
    logx=True,
    logy=True,
    equality_check=pd.DataFrame.equals)

34

value_countsはデフォルトでNaNを省略しているため、「」を扱っている可能性があります。

だからあなたはそれらを次のように除外することができます

filter = df["Tenant"] != ""
dfNew = df[filter]

1
@Bobsソリューションは私には機能しませんでした。df.dropna(subset = ['tenant']、inplace = True)は機能します。
Amrita Sawant 2015年

1
申し訳ありません。私はあなたが ""を扱っていると思いました。ソリューションを回答として投稿する必要があります
Bob Haffner 2015年

9

セルに空白がある状況があります、あなたはそれを見ることができません、使用してください

df['col'].replace('  ', np.nan, inplace=True)

空白をNaNとして置き換えるには、

df= df.dropna(subset=['col'])

5

このバリエーションを使用できます。

import pandas as pd
vals = {
    'name' : ['n1', 'n2', 'n3', 'n4', 'n5', 'n6', 'n7'],
    'gender' : ['m', 'f', 'f', 'f',  'f', 'c', 'c'],
    'age' : [39, 12, 27, 13, 36, 29, 10],
    'education' : ['ma', None, 'school', None, 'ba', None, None]
}
df_vals = pd.DataFrame(vals) #converting dict to dataframe

これは出力します(**-必要な行のみを強調表示します):

   age education gender name
0   39        ma      m   n1 **
1   12      None      f   n2    
2   27    school      f   n3 **
3   13      None      f   n4
4   36        ba      f   n5 **
5   29      None      c   n6
6   10      None      c   n7

したがって、「education」値を持たないものをすべて削除するには、以下のコードを使用します。

df_vals = df_vals[~df_vals['education'].isnull()] 

(「〜」はNOTを示します)

結果:

   age education gender name
0   39        ma      m   n1
2   27    school      f   n3
4   36        ba      f   n5

0

欠落しているファイルが存在する列を気にしない場合は、データフレームに名前がNewあり、新しいデータフレームを同じ変数に割り当てたいことを考慮して、単に実行します。

New = New.drop_duplicates()

特に列の空の値の行を削除したい場合は、Tenantこれで作業が行われます

New = New[New.Tenant != '']

これは、特定の値を持つ行を削除するためにも使用できます。文字列を必要な値に変更するだけです。

:空の文字列の代わりに、がある場合はNaN

New = New.dropna(subset=['Tenant'])
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.