根据条件从列表中删除元素

问题描述

我有以下代码

from collections import defaultdict
import pandas as pd

THRESHOLD = 3 

item_counts = defaultdict(int)

df = {'col1':['1 2 3 4 5 6 7','1 3 6 7','2 6 7']}
lines = pd.DataFrame(data=df)

print(lines)

for line in lines['col1']:
    for item in line.split():
        item_counts[item] += 1

print(item_counts)         
for line in lines['col1']:
    for item in line.split():
        if item_counts[item] < THRESHOLD:
            del item

print(lines)

我的目标是对每个项目进行计数,并将低于阈值的项目从我的数据框中删除在这种情况下,只应保留 6 和 7,其余的应删除。 defaultdict 工作正常,但删除项目不起作用。

你知道我做错了什么吗?

解决方法

使用 del 与从列表中删除元素不同。 考虑下面的例子

>>> x=1
>>> y=2
>>> lst = [x,y]
>>> del x
>>> print(lst)
[1,2]
>>> lst.remove(x)
Traceback (most recent call last):
  File "<input>",line 1,in <module>
NameError: name 'x' is not defined
>>> lst.remove(y)
>>> print(lst)
[1]
>>> print(y)
2

如您所见,在变量上使用 del 共享指向列表中元素的指针 只删除了离开列表的指针。 remove 正好相反。它从列表中删除了元素,但没有删除变量指针。

至于解决问题:迭代时不应该直接从列表中删除。

IMO 最好的解决方法是使用列表理解来创建一个仅包含所需元素的新列表并替换旧列表:

for line in lines['col1']:
    line = [item for item in line.split() if item >= THRESHOLD
    # line = ' '.join(line)

附言 如果您希望将行返回到字符串,请添加注释行

,

如果您不需要 DataFrame(我不明白您为什么要这样做),您可以这样做:

from collections import Counter

THRESHOLD = 3
lines = {'col1':['1 2 3 4 5 6 7','1 3 6 7','2 6 7']}

# make proper list of ints
z = {k: [[int(x) for x in v.split()] for v in vals] for k,vals in lines.items()}
print(z)
# {'col1': [[1,2,3,4,5,6,7],[1,[2,7]]}

# count the items within each value of the dict
z = {k: Counter(x for vals in arr for x in vals) for k,arr in z.items()}
print(z)
# {'col1': Counter({6: 3,7: 3,1: 2,2: 2,3: 2,4: 1,5: 1})}

# select the items that are seen at least THRESHOLD times
z = {col: [k for k,v in cnt.items() if v >= THRESHOLD] for col,cnt in z.items()}
print(z)
# {'col1': [6,7]}