我有一个pandas DataFrame,我想删除它中的行,其中特定列中的字符串长度大于2.我知道我可以df.dropna()用来摆脱包含any的行NaN,但我没有看到如何基于条件表达式删除行.
这个问题的答案似乎与我想要的非常接近 - 似乎我应该能够做到这样的事情:
df[(len(df['column name']) < 2)]
Run Code Online (Sandbox Code Playgroud)
但我得到错误:
KeyError: u'no item named False'
Run Code Online (Sandbox Code Playgroud)
谁能告诉我我做错了什么?
Use*_*ser 674
要直接回答这个问题的标题(我理解的不一定是OP的问题,但可以帮助其他用户遇到这个问题),一种方法是使用drop方法:
df = df.drop(some labels)
df = df.drop(df[<some boolean condition>].index)
例
要删除列"得分"<50的所有行:
df = df.drop(df[df.score < 50].index)
就地版(正如评论中所指出)
df.drop(df[df.score < 50].index, inplace=True)
多种条件
(参见布尔索引)
运营商是:
|foror,&forand和~fornot.必须使用括号对这些进行分组.
删除列"得分"<50和> 20的所有行
df = df.drop(df[(df.score < 50) & (df.score > 20)].index)
Bre*_*arn 144
当你这样做时,len(df['column name'])你只得到一个数字,即DataFrame中的行数(即列本身的长度).如果要应用于len列中的每个元素,请使用df['column name'].map(len).所以试试吧
df[df['column name'].map(len) < 2]
Run Code Online (Sandbox Code Playgroud)
Kab*_*ard 90
我正在寻找一个解决方案,我偶然发现了一个明显的方法,即只过滤数据帧并分配回原始数据帧,
df = df[df.score > 50]
Run Code Online (Sandbox Code Playgroud)
WeN*_*Ben 10
在 Pandas 中,您可以str.len处理边界并使用布尔结果对其进行过滤。
df[df['column name'].str.len().lt(2)]
Run Code Online (Sandbox Code Playgroud)
我将扩展@User的通用解决方案以提供drop免费的替代方案。这是针对根据问题标题(不是OP的问题)定向到此处的人员的
假设您要删除所有带有负值的行。一种班轮解决方案是:-
df = df[(df > 0).all(axis=1)]
Run Code Online (Sandbox Code Playgroud)
逐步说明:-
让我们生成一个5x5随机正态分布数据帧
np.random.seed(0)
df = pd.DataFrame(np.random.randn(5,5), columns=list('ABCDE'))
A B C D E
0 1.764052 0.400157 0.978738 2.240893 1.867558
1 -0.977278 0.950088 -0.151357 -0.103219 0.410599
2 0.144044 1.454274 0.761038 0.121675 0.443863
3 0.333674 1.494079 -0.205158 0.313068 -0.854096
4 -2.552990 0.653619 0.864436 -0.742165 2.269755
Run Code Online (Sandbox Code Playgroud)
设条件为删除负片。满足条件的布尔df:
df > 0
A B C D E
0 True True True True True
1 False True False False True
2 True True True True True
3 True True False True False
4 False True True False True
Run Code Online (Sandbox Code Playgroud)
满足条件的所有行的布尔系列 注意,如果该行中的任何元素失败,则该行被标记为false
(df > 0).all(axis=1)
0 True
1 False
2 True
3 False
4 False
dtype: bool
Run Code Online (Sandbox Code Playgroud)
最后根据条件从数据框中过滤出行
df[(df > 0).all(axis=1)]
A B C D E
0 1.764052 0.400157 0.978738 2.240893 1.867558
2 0.144044 1.454274 0.761038 0.121675 0.443863
Run Code Online (Sandbox Code Playgroud)
您可以分配回DF实际删除 VS 过滤器上面做ING
df = df[(df > 0).all(axis=1)]
可以很容易地扩展它以过滤出包含NaN的行(非数字项):
df = df[(~df.isnull()).all(axis=1)]
对于以下情况,也可以简化此操作:删除E列为负的所有行
df = df[(df.E>0)]
Run Code Online (Sandbox Code Playgroud)
我想以一些分析统计数据结尾,说明为什么@User的drop解决方案比基于原始列的过滤要慢:-
%timeit df_new = df[(df.E>0)]
345 µs ± 10.5 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
%timeit dft.drop(dft[dft.E < 0].index, inplace=True)
890 µs ± 94.9 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
Run Code Online (Sandbox Code Playgroud)
列基本上是Series一个NumPy数组,即可以免费索引的列。对于对基础内存组织如何发挥执行速度感兴趣的人们,这里有一个关于加速熊猫的好链接:
小智 5
如果您想根据列值的某些复杂条件删除数据框的行,那么以上面所示的方式编写可能会很复杂。我有以下更简单的解决方案,它始终有效。让我们假设您想要删除带有“标题”的列,因此首先将该列放入列表中。
text_data = df['name'].tolist()
Run Code Online (Sandbox Code Playgroud)
现在对列表的每个元素应用一些函数并将其放入熊猫系列中:
text_length = pd.Series([func(t) for t in text_data])
Run Code Online (Sandbox Code Playgroud)
就我而言,我只是想获取令牌的数量:
text_length = pd.Series([len(t.split()) for t in text_data])
Run Code Online (Sandbox Code Playgroud)
现在在数据框中添加一个额外的列,其中包含上述系列:
df = df.assign(text_length = text_length .values)
Run Code Online (Sandbox Code Playgroud)
现在我们可以在新列上应用条件,例如:
df = df[df.text_length > 10]
Run Code Online (Sandbox Code Playgroud)
def pass_filter(df, label, length, pass_type):
text_data = df[label].tolist()
text_length = pd.Series([len(t.split()) for t in text_data])
df = df.assign(text_length = text_length .values)
if pass_type == 'high':
df = df[df.text_length > length]
if pass_type == 'low':
df = df[df.text_length < length]
df = df.drop(columns=['text_length'])
return df
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
426270 次 |
| 最近记录: |