代码之家  ›  专栏  ›  技术社区  ›  Emi OB

将函数应用于两个panda列并将其分配回原始数据帧会引发未来警告

  •  1
  • Emi OB  · 技术社区  · 1 年前

    我有一个数据框架,其中有不同事物分布的平均值和标准差列(以及与问题无关的其他列)。我需要应用一个函数将这些数字转换为μ和西格玛,以传递到对数正态分布中(这个函数的作用与我的问题无关,所以我简化了它)。示例数据帧和函数如下:

    df = pd.DataFrame({'mean': [3, 11, 9, 19, 22],
                       'std': [10, 17, 10, 25, 30]})
    
    
    def log_normal_transform(mean_std):
        mu = mean_std[0]
        sigma = mean_std[1]
        return mu*2, sigma*2
    

    我想应用这个函数来转换数据帧中的mean和std列。我以前是这样申请的:

    df[['mean', 'std']].apply(log_normal_transform, axis=1)
    

    其返回具有变换后的数字的一系列元组:

        0
    0   (6, 20)
    1   (22, 34)
    2   (18, 20)
    3   (38, 50)
    4   (44, 60)
    

    现在,当我尝试将其分配回原始列时,如下所示:

    df[['mean', 'std']] = df[['mean', 'std']].apply(log_normal_transform, axis=1)
    

    我得到一个错误,列的长度与键的长度不相同(我理解)。我发现 this question 关于如何将一系列元组分配给多列,大多数答案都建议将该系列转换为列表,所以我尝试了这样做:

    df[['mean', 'std']] = df[['mean', 'std']].apply(log_normal_transform, axis=1).values.tolist()
    

    这确实有效,但我收到了未来的警告:

    <string>:2: FutureWarning: Series.__getitem__ treating keys as positions is deprecated. In a future version, integer keys will always be treated as labels (consistent with DataFrame behavior). To access a value by position, use `ser.iloc[pos]`
    

    我如何在不出现未来警告的情况下做到这一点,以便我的代码在未来版本中仍然有效?

    1 回复  |  直到 1 年前
        1
  •  1
  •   jezrael    1 年前

    问题出现在按位置选择值的函数中,解决方案是使用 Series.iat Series.iloc 也使用参数 result_type='expand' 在里面 DataFrame.apply :

    “展开”:类似列表的结果将变成列。

    def log_normal_transform(mean_std):
        mu = mean_std.iat[0]
        sigma = mean_std.iat[1]
        return mu*2, sigma*2
    

    或者按标签选择列:

    def log_normal_transform(mean_std):
        mu = mean_std['mean']
        sigma = mean_std['std']
        return mu*2, sigma*2
    

    df[['mean', 'std']] = df[['mean', 'std']].apply(log_normal_transform,
                                                    axis=1, result_type='expand')
    print (df)
       mean  std
    0     6   20
    1    22   34
    2    18   20
    3    38   50
    4    44   60