【问题标题】:Pandas How to filter a SeriesPandas 如何过滤系列
【发布时间】:2015-04-01 01:38:27
【问题描述】:

在执行 groupby('name') 并在其他列上使用 mean() 函数后,我有一个这样的系列

name
383      3.000000
663      1.000000
726      1.000000
737      9.000000
833      8.166667

谁能告诉我如何过滤掉平均值为 1.000000 的行?谢谢你,非常感谢你的帮助。

【问题讨论】:

  • 那么,您将如何根据给定条件过滤系列?

标签: python pandas


【解决方案1】:
In [5]:

import pandas as pd

test = {
383:    3.000000,
663:    1.000000,
726:    1.000000,
737:    9.000000,
833:    8.166667
}

s = pd.Series(test)
s = s[s != 1]
s
Out[0]:
383    3.000000
737    9.000000
833    8.166667
dtype: float64

【讨论】:

  • 我更喜欢下面的答案,因为它们可以链接起来(即无需定义 s 然后在表达式中使用它两次)。仅适用于 pandas 0.18。
  • 另见 piRSquared 的 answer 中的时序比较。
【解决方案2】:

另一种方法是先转换为DataFrame并使用query方法(假设你安装了numexpr):

import pandas as pd

test = {
383:    3.000000,
663:    1.000000,
726:    1.000000,
737:    9.000000,
833:    8.166667
}

s = pd.Series(test)
s.to_frame(name='x').query("x != 1")

【讨论】:

  • 我不认为将条件作为字符串传递是个好主意
  • 这会增加数据帧的所有开销,而且会非常慢。
【解决方案3】:

从pandas 0.18+版本过滤一个系列也可以如下完成

test = {
383:    3.000000,
663:    1.000000,
726:    1.000000,
737:    9.000000,
833:    8.166667
}

pd.Series(test).where(lambda x : x!=1).dropna()

结帐: http://pandas.pydata.org/pandas-docs/version/0.18.1/whatsnew.html#method-chaininng-improvements

【讨论】:

  • 方法链更好(让我想起了 Spark。)
  • 是的,但 Spark 在这种情况下做了一些更直观的事情:它只是删除了与谓词不匹配的行,这意味着不使用“.dropna()”部分,这显然是多余的我直到我阅读了文档。被那个咬了:D
【解决方案4】:

作为DACW pointed out,pandas 0.18.1 中有method-chaining improvements 可以很好地满足您的需求。

您可以将函数传递给.loc 索引器或系列索引器[],而不是使用.where,并避免调用.dropna

test = pd.Series({
383:    3.000000,
663:    1.000000,
726:    1.000000,
737:    9.000000,
833:    8.166667
})

test.loc[lambda x : x!=1]

test[lambda x: x!=1]

DataFrame 和 NDFrame 类支持类似的行为。

【讨论】:

  • 这是我最喜欢的答案,而且它似乎也是最快的,没有下降到 numpy (见时间比较)。
【解决方案5】:

如果你喜欢链式操作,也可以使用compress函数:

test = pd.Series({
383:    3.000000,
663:    1.000000,
726:    1.000000,
737:    9.000000,
833:    8.166667
})

test.compress(lambda x: x != 1)

# 383    3.000000
# 737    9.000000
# 833    8.166667
# dtype: float64

【讨论】:

  • 请注意 pandas.Series.compress 自 0.24.0 版起已弃用。 pandas.
【解决方案6】:

执行此操作的一种快速方法是使用numpy 进行重构以对底层数组进行切片。请参阅下面的时间安排。

mask = s.values != 1
pd.Series(s.values[mask], s.index[mask])

0
383    3.000000
737    9.000000
833    8.166667
dtype: float64

天真的时机

【讨论】:

  • ,我喜欢你的方法,我想知道如果我有多重面具怎么办。谢谢
  • @MenglongLi 取决于,你应该问一个问题。最有可能的是,您会将它们与 & 结合使用。掩码 = 掩码 1 & 掩码 2
【解决方案7】:

就我而言,我有一个 panda 系列,其中的值是字符元组

Out[67]
0    (H, H, H, H)
1    (H, H, H, T)
2    (H, H, T, H)
3    (H, H, T, T)
4    (H, T, H, H)

因此我可以使用索引来过滤系列,但要创建我需要apply 的索引。我的条件是“找到所有只有一个'H'的元组”。

series_of_tuples[series_of_tuples.apply(lambda x: x.count('H')==1)]

我承认它不是“可链接的”,(即注意我重复series_of_tuples 两次;您必须将任何临时系列存储到一个变量中,以便您可以对其调用 apply(...) )。

可能还有其他方法(除了.apply(...))可以逐元素操作以生成布尔索引。

许多其他答案(包括接受的答案)使用可链接的函数,例如:

  • .compress()
  • .where()
  • .loc[]
  • []

这些接受可调用 (lambdas)应用于系列,而不是应用于这些系列中的单个

因此,当我尝试将上述条件 / 可调用 / lambda 与任何可链接函数(如 .loc[])一起使用时,我的元组系列表现异常:

series_of_tuples.loc[lambda x: x.count('H')==1]

产生错误:

KeyError: 'Level H must be same as name (None)'

我很困惑,但它似乎在使用 Series.count series_of_tuples.count(...) function ,这不是我想要的。

我承认另一种数据结构可能更好:

  • 类别数据类型?
  • 一个数据框(元组的每个元素都变成一列)
  • 一系列字符串(只需将元组连接在一起):

这会创建一系列字符串(即通过连接元组;将元组中的字符连接到单个字符串上)

series_of_tuples.apply(''.join)

这样我就可以使用chainable Series.str.count

series_of_tuples.apply(''.join).str.count('H')==1

【讨论】:

    猜你喜欢
    • 2020-08-12
    • 2022-07-05
    • 1970-01-01
    • 1970-01-01
    • 2019-04-04
    • 1970-01-01
    • 2017-04-14
    • 2013-06-07
    • 2022-01-26
    相关资源
    最近更新 更多