如何在 dtype=str 的数据帧上使用 dropna?
How to use dropna on dataframes with dtype=str?
当我有这样的数据框时:
import pandas as pd
import numpy as np
df = pd.DataFrame(np.nan, index=list('abc'), columns=list('DEF'), dtype=float)
df.set_value('a', 'D', 4.0)
df.set_value('b', 'E', 10.0)
D E F
a 4.0 NaN NaN
b NaN 10.0 NaN
c NaN NaN NaN
我可以通过调用以下方法轻松删除仅包含 NaNs
的行:
df = df.dropna(how='all')
产生
D E F
a 4.0 NaN NaN
b NaN 10.0 NaN
如何在使用 dtype=str
初始化的数据帧上做同样的事情?以下不起作用:
df2 = pd.DataFrame(np.nan, index=list('abc'), columns=list('DEF'), dtype='str')
df2.set_value('a', 'D', 'foo')
df2.set_value('b', 'E', 'bar')
D E F
a foo n n
b n bar n
c n n n
然后命令
df2 = df2.dropna(how='all')
returns 未修改的数据框。
先调用df.replace
,再调用df.dropna
:
In [1576]: df2.replace('n', np.nan).dropna(how='all')
Out[1576]:
D E F
a foo NaN NaN
b NaN bar NaN
这似乎是最直接的选择。据我所知,一旦你用 dtype=str
初始化你的数据框,你就丢失了 NaN
s,所以这更像是一个最佳猜测替换(你可以有合法的非 NaN
条目n
被标记为误报并已删除)。
这是与 John Galt 类似的解决方案,但保留 NaN
s:
In [1584]: df2[~df2.eq('n')].dropna(how='all')
Out[1584]:
D E F
a foo NaN NaN
b NaN bar NaN
扩展 Andrew L 的评论,您无需转换为 dtype=str
即可设置值。您可以改用基于 .loc
的索引:
In [1586]: df2 = pd.DataFrame(np.nan, index=list('abc'), columns=list('DEF'))
...: df2.loc['a', 'D'] = 'foo'
...: df2.loc['b', 'E'] = 'bar'
...:
In [1587]: df2
Out[1587]:
D E F
a foo NaN NaN
b NaN bar NaN
c NaN NaN NaN
而现在,
In [1588]: df2.dropna(how='all')
Out[1588]:
D E F
a foo NaN NaN
b NaN bar NaN
他们不再是 NaN
。你可以像
一样过滤它们
In [503]: df2[~df2.eq('n').all(1)]
Out[503]:
D E F
a foo n n
b n bar n
由于您已将 np.nan
转换为 n <class 'str'>
,您还可以执行以下操作:
df2[~(df2 == 'n').all(axis=1)]
D E F
a foo n n
b n bar n
显然,如果您的真实数据可能包含 "n"。
,那么这样做是不安全的
您可以用真实的 numpy.nan
值替换您的字符串:
df2.replace('n',np.nan).dropna(how = 'all')
这会起作用,但也会更改您可能想要保留的数据框中的 'n'
值。在这种情况下,删除仅包含值 'n'
:
的行
df2[(df2.T != 'n').any()]
此外,第二种解决方案的计算效率更高:
%timeit df2.replace('n',np.nan).dropna(how = 'all')
985 µs ± 8.2 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
%timeit df2[(df2.T != 'n').any()]
449 µs ± 1.33 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
当我有这样的数据框时:
import pandas as pd
import numpy as np
df = pd.DataFrame(np.nan, index=list('abc'), columns=list('DEF'), dtype=float)
df.set_value('a', 'D', 4.0)
df.set_value('b', 'E', 10.0)
D E F
a 4.0 NaN NaN
b NaN 10.0 NaN
c NaN NaN NaN
我可以通过调用以下方法轻松删除仅包含 NaNs
的行:
df = df.dropna(how='all')
产生
D E F
a 4.0 NaN NaN
b NaN 10.0 NaN
如何在使用 dtype=str
初始化的数据帧上做同样的事情?以下不起作用:
df2 = pd.DataFrame(np.nan, index=list('abc'), columns=list('DEF'), dtype='str')
df2.set_value('a', 'D', 'foo')
df2.set_value('b', 'E', 'bar')
D E F
a foo n n
b n bar n
c n n n
然后命令
df2 = df2.dropna(how='all')
returns 未修改的数据框。
先调用df.replace
,再调用df.dropna
:
In [1576]: df2.replace('n', np.nan).dropna(how='all')
Out[1576]:
D E F
a foo NaN NaN
b NaN bar NaN
这似乎是最直接的选择。据我所知,一旦你用 dtype=str
初始化你的数据框,你就丢失了 NaN
s,所以这更像是一个最佳猜测替换(你可以有合法的非 NaN
条目n
被标记为误报并已删除)。
这是与 John Galt 类似的解决方案,但保留 NaN
s:
In [1584]: df2[~df2.eq('n')].dropna(how='all')
Out[1584]:
D E F
a foo NaN NaN
b NaN bar NaN
扩展 Andrew L 的评论,您无需转换为 dtype=str
即可设置值。您可以改用基于 .loc
的索引:
In [1586]: df2 = pd.DataFrame(np.nan, index=list('abc'), columns=list('DEF'))
...: df2.loc['a', 'D'] = 'foo'
...: df2.loc['b', 'E'] = 'bar'
...:
In [1587]: df2
Out[1587]:
D E F
a foo NaN NaN
b NaN bar NaN
c NaN NaN NaN
而现在,
In [1588]: df2.dropna(how='all')
Out[1588]:
D E F
a foo NaN NaN
b NaN bar NaN
他们不再是 NaN
。你可以像
In [503]: df2[~df2.eq('n').all(1)]
Out[503]:
D E F
a foo n n
b n bar n
由于您已将 np.nan
转换为 n <class 'str'>
,您还可以执行以下操作:
df2[~(df2 == 'n').all(axis=1)]
D E F
a foo n n
b n bar n
显然,如果您的真实数据可能包含 "n"。
,那么这样做是不安全的您可以用真实的 numpy.nan
值替换您的字符串:
df2.replace('n',np.nan).dropna(how = 'all')
这会起作用,但也会更改您可能想要保留的数据框中的 'n'
值。在这种情况下,删除仅包含值 'n'
:
df2[(df2.T != 'n').any()]
此外,第二种解决方案的计算效率更高:
%timeit df2.replace('n',np.nan).dropna(how = 'all')
985 µs ± 8.2 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
%timeit df2[(df2.T != 'n').any()]
449 µs ± 1.33 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)