pandas中的大多数操作都可以通过操作符链接(groupby、聚合、应用等)来完成,但我发现过滤行的唯一方法是通过普通的括号索引

df_filtered = df[df['column'] == value]

这是没有吸引力的,因为它要求我分配df到一个变量,然后才能过滤它的值。还有像下面这样的吗?

df_filtered = df.mask(lambda x: x['column'] == value)

当前回答

所以我的看法是,在对数据进行细分以备分析时,你要做两件事。

就行 获得列

Pandas有很多方法来实现这些,还有一些技术可以帮助获取行和列。对于熊猫的新用户来说,选择太多了,可能会感到困惑。

你使用iloc, loc,括号,查询,isin, np。在哪里,面具等等…

方法链接

方法链接是处理数据争执的好方法。在R中,它们有一种简单的方法来做到这一点,你选择()列和过滤()行。

因此,如果我们想在Pandas中保持简单,为什么不对列使用filter(),对行使用query()呢?它们都返回数据框架,所以不需要在布尔索引上添乱,不需要在返回值周围添加df[]。

那它看起来像什么呢? -

df.filter(['col1', 'col2', 'col3']).query("col1 == 'sometext'")

然后你可以链上任何其他方法,如groupby, dropna(), sort_values(), reset_index()等。

通过保持一致并使用filter()来获取列,使用query()来获取行,当一段时间后回到代码时,将更容易阅读您的代码。

但是过滤器可以选择行吗?

是的,这是真的,但默认情况下query()获取行和filter()获取列。因此,如果您坚持使用默认值,则不需要使用axis=参数。

查询()

Query()可以同时使用和/或&/|,你也可以使用比较运算符>,<,>=,<=,==,!=。你也可以使用Python in,而不是in。

您可以使用@my_list将一个列表传递给查询

一些使用查询获取行的示例

df.query('A > B')

df.query('a not in b')

df.query("series == '2206'")

df.query("col1 == @mylist")

df.query('Salary_in_1000 >= 100 & Age < 60 & FT_Team.str.startswith("S").values')

filter ()

所以filter基本上就像使用方括号df[]或df[[]],因为它使用标签来选择列。但它不仅仅是括号符号。

过滤器有like= param,以帮助选择有部分名称的列。

df.filter(like='partial_name',)

过滤器也有正则表达式来帮助选择

df.filter(regex='reg_string')

综上所述,这种工作方式可能并不适用于任何情况,例如,如果你想使用索引/切片,那么iloc是正确的选择。但这似乎是一种可靠的工作方式,可以简化您的工作流程和代码。

其他回答

过滤器可以使用Pandas查询链接:

df = pd.DataFrame(np.random.randn(30, 3), columns=['a','b','c'])
df_filtered = df.query('a > 0').query('0 < b < 2')

过滤器也可以在单个查询中组合:

df_filtered = df.query('a > 0 and 0 < b < 2')

如果你想应用所有常见的布尔掩码以及一个通用的掩码,你可以在一个文件中输入以下内容,然后简单地将它们分配如下:

pd.DataFrame = apply_masks()

用法:

A = pd.DataFrame(np.random.randn(4, 4), columns=["A", "B", "C", "D"])
A.le_mask("A", 0.7).ge_mask("B", 0.2)... (May be repeated as necessary

这有点老套,但如果你根据过滤器不断地切割和改变数据集,它可以让事情变得更干净。 在gen_mask函数中也有一个通用的过滤器,你可以使用lambda函数或其他如果需要的话。

要保存的文件(我使用mask .py):

import pandas as pd

def eq_mask(df, key, value):
    return df[df[key] == value]

def ge_mask(df, key, value):
    return df[df[key] >= value]

def gt_mask(df, key, value):
    return df[df[key] > value]

def le_mask(df, key, value):
    return df[df[key] <= value]

def lt_mask(df, key, value):
    return df[df[key] < value]

def ne_mask(df, key, value):
    return df[df[key] != value]

def gen_mask(df, f):
    return df[f(df)]

def apply_masks():

    pd.DataFrame.eq_mask = eq_mask
    pd.DataFrame.ge_mask = ge_mask
    pd.DataFrame.gt_mask = gt_mask
    pd.DataFrame.le_mask = le_mask
    pd.DataFrame.lt_mask = lt_mask
    pd.DataFrame.ne_mask = ne_mask
    pd.DataFrame.gen_mask = gen_mask

    return pd.DataFrame

if __name__ == '__main__':
    pass

所以我的看法是,在对数据进行细分以备分析时,你要做两件事。

就行 获得列

Pandas有很多方法来实现这些,还有一些技术可以帮助获取行和列。对于熊猫的新用户来说,选择太多了,可能会感到困惑。

你使用iloc, loc,括号,查询,isin, np。在哪里,面具等等…

方法链接

方法链接是处理数据争执的好方法。在R中,它们有一种简单的方法来做到这一点,你选择()列和过滤()行。

因此,如果我们想在Pandas中保持简单,为什么不对列使用filter(),对行使用query()呢?它们都返回数据框架,所以不需要在布尔索引上添乱,不需要在返回值周围添加df[]。

那它看起来像什么呢? -

df.filter(['col1', 'col2', 'col3']).query("col1 == 'sometext'")

然后你可以链上任何其他方法,如groupby, dropna(), sort_values(), reset_index()等。

通过保持一致并使用filter()来获取列,使用query()来获取行,当一段时间后回到代码时,将更容易阅读您的代码。

但是过滤器可以选择行吗?

是的,这是真的,但默认情况下query()获取行和filter()获取列。因此,如果您坚持使用默认值,则不需要使用axis=参数。

查询()

Query()可以同时使用和/或&/|,你也可以使用比较运算符>,<,>=,<=,==,!=。你也可以使用Python in,而不是in。

您可以使用@my_list将一个列表传递给查询

一些使用查询获取行的示例

df.query('A > B')

df.query('a not in b')

df.query("series == '2206'")

df.query("col1 == @mylist")

df.query('Salary_in_1000 >= 100 & Age < 60 & FT_Team.str.startswith("S").values')

filter ()

所以filter基本上就像使用方括号df[]或df[[]],因为它使用标签来选择列。但它不仅仅是括号符号。

过滤器有like= param,以帮助选择有部分名称的列。

df.filter(like='partial_name',)

过滤器也有正则表达式来帮助选择

df.filter(regex='reg_string')

综上所述,这种工作方式可能并不适用于任何情况,例如,如果你想使用索引/切片,那么iloc是正确的选择。但这似乎是一种可靠的工作方式,可以简化您的工作流程和代码。

如果将列设置为作为索引进行搜索,则可以使用DataFrame.xs()获取横截面。这没有查询答案那么通用,但在某些情况下可能很有用。

import pandas as pd
import numpy as np

np.random.seed([3,1415])
df = pd.DataFrame(
    np.random.randint(3, size=(10, 5)),
    columns=list('ABCDE')
)

df
# Out[55]: 
#    A  B  C  D  E
# 0  0  2  2  2  2
# 1  1  1  2  0  2
# 2  0  2  0  0  2
# 3  0  2  2  0  1
# 4  0  1  1  2  0
# 5  0  0  0  1  2
# 6  1  0  1  1  1
# 7  0  0  2  0  2
# 8  2  2  2  2  2
# 9  1  2  0  2  1

df.set_index(['A', 'D']).xs([0, 2]).reset_index()
# Out[57]: 
#    A  D  B  C  E
# 0  0  2  2  2  2
# 1  0  2  1  1  0

来自@lodagro的答案很棒。我将通过泛化掩码函数来扩展它:

def mask(df, f):
  return df[f(df)]

然后你可以这样做:

df.mask(lambda x: x[0] < 0).mask(lambda x: x[1] > 0)