Python 如何在dtype=str的数据帧上使用dropna?
当我有这样一个数据帧时:Python 如何在dtype=str的数据帧上使用dropna?,python,pandas,dataframe,nan,missing-data,Python,Pandas,Dataframe,Nan,Missing Data,当我有这样一个数据帧时: 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 Na
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
df2[~(df2 == 'n').all(axis=1)]
D E F
a foo n n
b n bar n
通过调用以下命令,我可以轻松删除只包含nan
的行:
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')
返回未修改的数据帧。首先调用
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
条目,它们被标记为误报并被删除)
这里有一个类似于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
首先调用
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
条目,它们被标记为误报并被删除)
这里有一个类似于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
它们不再是
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
,您还可以执行以下操作:
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
df2[~(df2 == 'n').all(axis=1)]
D E F
a foo n n
b n bar n
显然,如果您可能有包含“n”的真实数据,这是不安全的。因为您已将
np.nan
转换为n
,您还可以执行以下操作:
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
df2[~(df2 == 'n').all(axis=1)]
D E F
a foo n n
b n bar n
显然,如果您的实际数据可能包含“n”,则这是不安全的。您可以将字符串替换为real
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)
您可以用real
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)
它们不再是NaN,而是char
'n'
,所以你可以把它们过滤掉,但这里真正的问题是什么,NaN
是一个数字事物,str
不能表示它,所以从技术上讲它们不是NaN
它们不再是NaN
,而是字符'n'
,所以你可以把它们过滤掉,但这里真正的问题是什么,NaN
是一个数字的东西,str
不能表示它,所以它们在技术上不是NaN
Ok,这是一个令人不快的问题,但却是一个可靠的解决方案(上标)。当我没有指定dtype
时,我不能将set_值
与字符串一起使用,不幸的是…@Cleb为什么不使用loc
设置值df2.loc['a',D']='foo'
@AndrewL:Withloc
它确实有效,但与set\u值
不起作用,后者应该更快。@Cleb是的,但是将n
s转换为NaN
s的惩罚将是你所遭受的。一定要重新考虑。我已经添加了一个MVCE来支持这个概念。谢谢,是的,我可能会选择loc
;我只是想知道是否有更好的解决方案,谢谢你的详细回答。好的,这是一个令人不快的但却是一个坚实的工作(投票表决)。当我没有指定dtype
时,我不能将set_值
与字符串一起使用,不幸的是…@Cleb为什么不使用loc
设置值df2.loc['a',D']='foo'
@AndrewL:Withloc
它确实有效,但与set\u值
不起作用,后者应该更快。@Cleb是的,但是将n
s转换为NaN
s的惩罚将是你所遭受的。一定要重新考虑。我已经添加了一个MVCE来支持这个概念。谢谢,是的,我可能会选择loc
;我只是想知道是否有更好的解决方案,谢谢你的详细回答;这并不理想,因为实际数据可能等于n
@Cleb,这恐怕是任何解决方案都要冒的风险;这不太理想,因为实际数据可能等于n
@Cleb,我想这是一个你必须采取任何解决方案的机会。与另一个答案相同,但在时间比较上仍然投了较高的票。我最初投了你的反对票,因为这也是我的答案。现在我看到你添加了更多的内容,我删除了它,但你应该知道我知道是你报复否决了我的三个答案。这怎么可能是报复?我不知道是你投票否决了我。即使我做到了,我也不在乎。我对您的一些答案投了反对票,因为它们要么效率低下(例如使用lambda函数,基本上用于循环),要么有副作用(转换不需要的数据类型)。如果这伤害了你的感情,我很抱歉。嗯。。。如果是这样的话,你会有更多的答案被否决:)你应该在否决之前三思而后行,尤其是在愤怒/报复中否决。我不明白为什么这意味着