Python Pandas - 根据值删除行

时间:2017-02-17 20:05:04

标签: python python-2.7 pandas numpy dataframe

我有一个Pandas数据框,其中包含A列和B列

Sub InsertClient()

lastrow = Cells(Rows.Count, "A").End(xlUp).Row

    For i = lastrow To 2 Step -1
        If i = lastrow Then
        Range("A" & i + 1).Value = Range("A" & i).Value
        End If

        If Range("A" & i).Value <> Range("A" & i - 1).Value Then
        Rows(i).Insert shift:=xlShiftDown
        Range("A" & i).Value = Range("A" & i - 1).Value
        End If

    Next i

End Sub

我创建了列C,如果import pandas as pd import numpy as np df = pd.DataFrame(np.random.randint(0,100,size=(10, 2)), columns=list('AB'))

,则为NULL
A > B

这给出了:

df['C'] = np.select([ df.A > df.B ], [df.A], default=np.NaN)

然后,我使用以下几种方法之一删除具有df.C作为NaN的行:

    A   B     C
0  95  19  95.0
1  46  11  46.0
2  96  86  96.0
3  22  61   NaN
4  69   1  69.0
5  78  91   NaN
6  42   7  42.0
7  24  28   NaN
8  55  92   NaN
9  92  16  92.0

df = df.dropna(subset=['C'], how='any')

df = df.drop(df[pd.isnull(df.C)].index)

并且所有3种方法都让我大致有行。在这种情况下:

df = df.drop(df[(pd.isnull(df.C))].index)

但是当我不使用数字时,例如字符串:

    A   B     C
0  95  19  95.0
1  46  11  46.0
2  96  86  96.0
4  69   1  69.0
6  42   7  42.0
9  92  16  92.0

然后,不会过滤那些删除df.C为NaN的行的3种方法。例如,当df['C'] = np.select([ df.A > df.B ], ['yes'], default=np.NaN) 将C列设置为df.A > df.B时,我会得到类似的结果:

yes

我可以解决这个问题,将pd.NaN替换为&#39; IGNORE&#39;等字符串,然后过滤&#39; IGNORE&#39;,但我发现这个结果是出乎意料的。

    A   B    C
0   6  70  nan
1  85  46  yes
2  76  87  nan
3  77  36  yes
4  73  18  yes
5   1  41  nan
6  19  69  nan
7  62  89  nan
8   6   7  nan
9  35  75  nan

这里发生了什么? (当df.C是一个字符串时,我的pd.NaN被转换为字符串吗?)

我在Windows 10上使用64位Python 2.7.13,Pandas 0.19.2和Numpy 1.11.3。

2 个答案:

答案 0 :(得分:2)

而不是删除,只取有限值。

df = df[np.isfinite(df['C'])]

编辑:

根据您的评论nan属于string类型,因此,请根据值删除行:

df = df[df.C != "nan"]将有效

df[df.C.notnull()]
    A   B    C
0  67  23  yes
1  91  61  yes
2  30  92  nan
3  53  97  nan
4  81  11  yes
5  23   7  yes
6  47  39  yes
7  11  27  nan
8  46  55  nan
9  31  82  nan
df = df[df.C != "nan"]


    A   B    C
0  67  23  yes
1  91  61  yes
4  81  11  yes
5  23   7  yes
6  47  39  yes 

答案 1 :(得分:1)

您的案例与此类似:

np.array([1,2,'3',np.nan])
# array(['1', '2', '3', 'nan'], 
#       dtype='<U21')

因为np.select也会返回一个数组,如果你进一步检查

type(np.nan)
# float

str(np.nan)
# 'nan'

所以np.nan是一个浮点数,但是numpy数组比structured array更喜欢单个数据类型,所以当数组中有一个字符串元素时,所有元素都转换为字符串。

对于您的情况,如果您有字符串列,则可以使用None代替np.nan作为默认值,这将创建一个缺失值,可以通过isnull()检查并使用dropna()

import pandas as pd
import numpy as np
​
df = pd.DataFrame(np.random.randint(0,100,size=(10, 2)), columns=list('AB'))
df['C'] = np.select([ df.A > df.B ], ['yes'], default=None)

df.dropna()

#    A  B     C
#0  82  1   yes
#3  84  8   yes
#6  52  30  yes
#7  68  61  yes
#9  91  87  yes