For循环没有过滤掉数据帧系列中的关键字

2024-05-16 21:12:15 发布

您现在位置:Python中文网/ 问答频道 /正文

下面是表示我的数据帧的模拟数据:

Arkansa  4  McKissic Creek Rd       HVAC/Plumbing
Florida  0  1130 Birdie Hills Rd    Lawn Care
Missouri 3  1140 Birdie Hills Rd    Interiors
Texas.   2  11625 Rainbow Ridge     Electrical

下面是我的脚本,它应该从原始数据框(bool_filtered_df)中选择整行,并添加到列表中(稍后我将其转换为自己的数据框),如果次垂直(第4列)是“电气”、“管道清洁”、“水处理”或“设备维修”然而,它并没有过滤掉任何我能说出来的东西,我也不明白为什么。谢谢你的帮助。谢谢

for d in range(0, len(bool_filtered_df)):
    try:
        if "Electrical" or "Duct Cleaning" or "Water Treatment" or "Appliance Repair" in bool_filtered_df['Sub-Vertical'][d]:
            Geneva_Trais.append(bool_filtered_df.iloc[d])
        else:
            print("Wrong Sub-Vert")
    except TypeError as t:
        print(t)
        continue

Tags: or数据indfrdelectricalfilteredbool
3条回答

修复原始问题

Tim Roberts described这个问题

这有时被称为“orgotcha”。初学者很容易忘记Python是一种具有严格规则的编程语言,因此他们错误地猜测类似于英语写作的语法。这是一个不正确的猜测

代码的一个正确翻译是:

Geneva_Trais = []
for d in range(0, len(bool_filtered_df)):
    sub_vert = bool_filtered_df['Sub-Vertical'].iloc[d]
    if (
        "Electrical" in sub_vert or
        "Duct Cleaning" in sub_vert or
        "Water Treatment" in sub_vert or
        "Appliance Repair" in sub_vert
    ):
        Geneva_Trais.append(bool_filtered_df.iloc[d])
    else:
        print(f"Wrong Sub-Vert: {idx}, {sub_vert}")

请注意,您在原始代码中也混合了[].iloc[],这是一个非常糟糕的想法^序列上的{}等价于.loc[],它仅在非常特定的情况下等价于.iloc[]。这些情况恰好是默认情况,因此新手往往会掩盖非常重要的区别

更有效地循环

您还可以在一个系列的元素上循环,而无需在每次迭代时使用.iloc,这样既快又整洁:

Geneva_Trais = []
for idx, sub_vert in bool_filtered_df['Sub-Vertical'].items():
    if (
        ("Electrical" in sub_vert) or
        ("Duct Cleaning" in sub_vert) or
        ("Water Treatment" in sub_vert) or
        ("Appliance Repair" in sub_vert)
    ):
        Geneva_Trais.append(bool_filtered_df.loc[idx])
    else:
        print(f"Wrong Sub-Vert: {idx}, {sub_vert}")

G.Anderson无环近似

如果将这些字符串与==进行精确比较是有意义的,那么我们可以使用isin中描述的isin方法并完全避免循环:

sub_verts = [
    'Electrical', 'Duct Cleaning', 'Water Treatment', 'Appliance Repair'
]

Geneva_Trais = bool_filtered_df.loc[
    bool_filtered_df['Sub-Vertical'].isin(sub_verts)
]

根据您提供的示例数据,这可能是您的意图

此技术还返回数据帧,而不是序列列表

注意,我个人更喜欢使用.loc[]而不是[]进行行的布尔子集设置。我只使用[]按名称选择列。这是为了避免错误地选择错误的东西

精确的无循环翻译

但是,原始代码的行为与.isin技术不同。您的代码检查4个字符串中的每一个是否都是序列中值的子字符串。正确的代码无循环翻译应为:

def check_sub_vert(sub_vert):
    return (
        "Electrical" in sub_vert or
        "Duct Cleaning" in sub_vert or
        "Water Treatment" in sub_vert or
        "Appliance Repair" in sub_vert
    )

is_ok = bool_filtered_df['Sub-Vertical'].apply(check_sub_vert)
Geneva_Trais = bool_filtered_df.loc[is_ok]

4in检查仍然存在,但是我们已经将它们移动到一个单独的函数中。我们可以使用.apply来收集在每个元素上调用此函数的结果,而无需使用for循环。在许多情况下,这比循环快得多,并且通常是首选的使用方式。有时这种风格被称为“矢量化”

本声明:

        if "Electrical" or "Duct Cleaning" or "Water Treatment" or "Appliance Repair" in bool_filtered_df['Sub-Vertical'][d]:

被解释为:

        if ("Electrical") or ("Duct Cleaning") or ("Water Treatment") or ("Appliance Repair" in bool_filtered_df['Sub-Vertical'][d]):

因为“电气”是真的,所以if语句总是真的。您可以尝试以下方法:

    if bool_filtered_df['Sub-Vertical'][d] in ('Electrical', 'Duct Cleaning', 'Water Treatment', 'Appliance Repair'):

您可以对Series.isin()使用内置布尔筛选

bool_filtered_df[bool_filtered_df['Sub-Vertical'].isin(['Electrical', 'Duct Cleaning', 'Water Treatment', 'Appliance Repair'])]

相关问题 更多 >