高效处理 pandas 数据帧,无需嵌套 for 循环或修改副本而不是原始数据

问题描述 投票:0回答:1

我的设置是我想浏览我的数据框 df 并将特定值更改为缺失。

具体来说,从另一个数据框边界,我检查列特定的下限和上限,以及给定的开始值和结束值是否适合它们。如果 df 中的值不适合边界,那么我想将 df 中的整个列设置为缺失。如果是,那么我想检查 df 索引的特定部分是否在边界内。如果没有,那么我想将该特定单元格设置为缺失。

我的边界数据框的格式如下所示:

索引
第 1 栏 1 102
第 1 栏 103 244
第 1 栏 245 440
第 2 栏 1 99
第 2 栏 100 288
第 2 栏 289 427

df 中索引的格式为“Alice:220:A:B”、“Bob:87:B:C”等

我当前的方法效率低下,并且在尝试使用 None 作为缺失类型时会引发未来警告 - df 中的数据类型是 float64。当尝试 np.nan 时,我收到有关修改副本而不是原始文件的警告,我想修改原始文件。

这是我迄今为止尝试过的:

    def filter_by_bounds(self, start, end, df):

        for cur_col in df.columns:
            cur_bounds = self.bounds.loc[
                (self.bounds.index == cur_col)
                & (self.bounds["lower"] <= start)
                & (self.bounds["upper"] >= start)
            ]

            for id in df.index:
                cur_pos = int(id.split(":")[1])

                # First check start and end fall into one row in bounds
                if len(cur_bounds) != 1:
                    df.loc[:, cur_col] = None
                    break
                # Then check if the current positions falls into the current bounds
                elif (
                    cur_bounds["lower"].values[0] > cur_pos
                    or cur_bounds["upper"].values[0] < cur_pos
                ):
                    df.loc[df.index == id, cur_col] = None

        return df

这种方法可行,但我更愿意摆脱嵌套循环并使用例如屏蔽来提高效率。另外,我目前将值修改为缺失的方法是有问题的,我想正确地做到这一点。

任何解决此问题的帮助将不胜感激:)

python pandas dataframe
1个回答
0
投票

您确实可以通过利用矢量化操作和布尔掩码来提高代码效率并避免嵌套循环。此外,要在不发出警告的情况下修改原始 DataFrame,您可以使用带有布尔索引的

.loc
访问器。这是您的函数的修订版本:

import pandas as pd
import numpy as np

class YourClass:
    def __init__(self, bounds):
        self.bounds = bounds

    def filter_by_bounds(self, df):
        # Create an empty mask to mark cells to be set to missing
        mask = pd.Series(index=df.index, data=False)

        for cur_col in df.columns:
            cur_bounds = self.bounds.loc[self.bounds.index == cur_col]

            # Find the lower and upper bounds for the current position
            lower_bound = cur_bounds["lower"].values
            upper_bound = cur_bounds["upper"].values

            # Extract current position from index and check if it falls into bounds
            positions = df.index.str.split(":").str[1].astype(int)
            within_bounds = (positions >= lower_bound) & (positions <= upper_bound)

            # Update mask for the current column
            mask_cur_col = (self.bounds.index == cur_col) & ~within_bounds.any()
            mask |= mask_cur_col[df.index]

        # Use boolean mask to set values to missing
        df[mask] = np.nan

        return df

# Example usage
bounds_data = {
    'index': ['Col1', 'Col1', 'Col1', 'Col2', 'Col2', 'Col2'],
    'lower': [1, 103, 245, 1, 100, 289],
    'upper': [102, 244, 440, 99, 288, 427]
}
bounds_df = pd.DataFrame(bounds_data)

your_instance = YourClass(bounds_df)

# Example DataFrame df
data = {
    'Alice:220:A:B': [10, 20, 30],
    'Bob:87:B:C': [105, 200, 300],
    'Charlie:300:C:D': [250, 350, 450]
}
df = pd.DataFrame(data)

# Apply the filter
filtered_df = your_instance.filter_by_bounds(df)
print(filtered_df)

此代码应该有效地迭代列,根据边界为每列创建一个掩码,然后使用该掩码将原始 DataFrame 中的值设置为缺失

df
,而无需修改副本。

© www.soinside.com 2019 - 2024. All rights reserved.