【问题标题】:How can I keep the rows of a pandas data frame that match a particular condition using value_counts() on multiple columns如何在多列上使用 value_counts() 保留与特定条件匹配的 pandas 数据帧的行
【发布时间】:2019-12-09 00:41:33
【问题描述】:

考虑到 3 列,我想删除那些特定值在一列中只出现一次的行。也就是说,对于功能:

  • 文本:如果 value_counts() == 1,则消除这些行,或者仅在 value_counts() > 1 时保留
  • next_word:如果 value_counts() == 1,则消除这些行,或者仅在 value_counts() > 1 时保留。在这种情况下,只需使用已处理的行(仅保留“文本”列包含的行值出现多次)
  • previous_word:如果 value_counts() == 1,则消除这些行,或者仅在 value_counts() > 1 时保留。在这种情况下,使用已处理的案例(只保留列“文本”和'next_word' 包含多次出现的值)

我已经尝试过获取一个数据框,该数据框保留包含特定列中这些值的行:

#text
text_counts = df_processed['text'].value_counts()
text_list = text_counts[text_counts > 1].index.tolist()
zip_data_text_removed = df_processed[df_processed['text'].isin(text_list)] 

如果我显示此特定列“文本”的 value_counts:zip_data_text_removed.text.value_counts()

我可以检查我得到的数据框是否包含多次出现的值,即 50539 个初始唯一值中的 25470 个唯一值(这是正确的)。但是,当我显示有关数据框的信息时:

类'pandas.core.frame.DataFrame' Int64Index:291442 个条目,0 到 316510

显然不匹配。

我还想对其余列应用相同的方法(现在,使用之前的过滤数据框):

#Next
next_word_counts = df_processed['next_word'].value_counts()
next_word_list = next_word_counts[next_word_counts > 1].index.tolist()
zip_data_next_text_removed = zip_data_text_removed[zip_data_text_removed['next_word'].isin(next_word_list)]


#Previous
previous_word_counts = df_processed['previous_word'].value_counts()
previous_word_list = previous_word_counts[previous_word_counts > 1].index.tolist()
zip_data_prev_text_removed = zip_data_next_text_removed[zip_data_next_text_removed['previous_word'].isin(previous_word_list)]

但是,当我显示“文本”的 value_counts 时,即使用的第一个功能:

zip_data_prev_text_removed.text.value_counts()

它还显示仅出现一次的值.. 这很奇怪。数据框的信息也比较混乱:

类'pandas.core.frame.DataFrame' Int64Index:247621 个条目,0 到 316509

不应该是从 0 到 247621 个条目吗?

***编辑

现在,我按照@janPansky 的建议添加了 reset_index(drop=True):

#text
text_counts = df_processed['text'].value_counts()
text_list = text_counts[text_counts > 1].index.tolist()
zip_data_text_removed = df_processed[df_processed['text'].isin(text_list)]
zip_data_text_removed = zip_data_text_removed.reset_index(drop=True) 

#Next
next_word_counts = zip_data_text_removed['next_word'].value_counts()
next_word_list = next_word_counts[next_word_counts > 1].index.tolist()
zip_data_next_text_removed = zip_data_text_removed[zip_data_text_removed['next_word'].isin(next_word_list)]
zip_data_next_text_removed = zip_data_next_text_removed.reset_index(drop=True)
print(zip_data_next_text_removed.text.value_counts() )  

但是,仍然继续打印 value_count == 1 的值

【问题讨论】:

  • 在不重置索引的情况下删除行之前是否进行了一些操作?
  • @Mayeulsgc 是的,只是将某些列的值转换为小写: df_processed['text'] = df_processed['text'].apply(lambda x: x.lower())
  • 你能澄清你在第一句话中的意思吗?您是否要删除所有具有仅在三列中的任何一列中出现一次的值的行?或者您是否尝试删除具有在所有列中出现一次的值的行?
  • @maltodextrin 在第一个原始帖子中查看上面的编辑

标签: python pandas dataframe


【解决方案1】:

如果我正确理解您的问题,仍然有点不确定,但看看这种不同的方法是否能满足您的需求。我将它拆开以使其易于理解,但也可以用丑陋的单线来完成。

counts_text = df_processed['text'].value_counts()
non_unique_text = df_processed['text'].apply(lambda text: counts_text[text]>1)

我们在这里使用 value_counts() 的结果作为各种字典。

所以现在我们对每一行都有一系列布尔值,说明该行中的值是否不唯一。您可以对其他每一列执行相同的操作来制作 non_unique_nextwordnon_unique_prevword,只需将上面的所有文本实例替换为相应的列标题即可。

最后,我们只使用逻辑 AND 来保留在三列中的每一列中具有非唯一值的行。然后我们可以通过简单的索引从原始数据帧中得到最终的数据帧:

df_nonunique = df_processed[non_unique_test & non_unique_nextword & non_unique_prevword]

让我知道这是否离谱。

【讨论】:

  • 仍然,这不起作用。如果我打印最终数据帧的 value_counts,我仍然可以看到有 1 次出现的值。
  • 哦,我想我可能知道问题所在。因为我们都是按顺序过滤的,所以在第二个过滤器之后,第一列中可能有一些行曾经具有非唯一值,而这些行已经变得唯一。这对您的用例来说是个问题吗?
  • 没错!这正是正在发生的事情。通过消除第二个特征中的行,包含在第一个特征中出现 2 次的值的行最终将变为出现 1 次的行。问题是 text、next_word 和 prev_words 相互依赖,所以我想这应该无关紧要。谢谢!
猜你喜欢
  • 2021-05-20
  • 2020-02-25
  • 1970-01-01
  • 2022-11-01
  • 2020-09-13
  • 1970-01-01
  • 1970-01-01
  • 2021-01-07
  • 1970-01-01
相关资源
最近更新 更多