繁体   English   中英

在 pandas 中,如何将符合条件的值替换为其列名称中的值?

[英]In pandas, how to replace values matching a condition with a value from the names of their columns?

我正在写一个 function 作为输入 dataframe 和一个“掩码”。 假定数据框具有多索引列,例如("some string", 0.4) :对,其中第二个 object 是数字。 掩码旨在类似于df < 2df >= 4等。

output 应该是一个新表,其中每个与掩码不匹配的值都被保留,每个匹配的值都被其列名的数字替换。

输入中的 NaN 应该单独保留(当然除非掩码类似于df.isna() )。

这就是我想出的(假设这是在一个名为mytable.py的文件中):

import pandas as pd
import numpy as np


data = {
    ("A", 0.2): [4.0, 1.0, np.nan],
    ("B", 0.6): [0.0, np.nan, 4.0],
    ("C", 0.7): [0.0, 5.0, 1.0],
}
df = pd.DataFrame(data)


def replaced_with_colname(table, mask):
    series1 = (table[col][mask[col]] for col in table.columns)
    series2 = (s.apply(lambda x: s.name[1]) for s in series1)
    t2 = table.copy()
    for s in series2:
        t2.update(s)
    return t2

一个例子:

$ python3 -i mytable.py
>>> df
     A    B    C
   0.2  0.6  0.7
0  4.0  0.0  0.0
1  1.0  NaN  5.0
2  NaN  4.0  1.0
>>> replaced_with_colname(df, df>2)
     A    B    C
   0.2  0.6  0.7
0  0.2  0.0  0.0
1  1.0  NaN  0.7
2  NaN  0.6  1.0

它似乎可以完成这项工作,但它看起来很复杂而且可能很慢,尽管我没有对它进行基准测试。 我的问题是:是否有(更多)“矢量化”的惯用方式? 使用更多 pandas 方法和更少的 for 循环?

对我有帮助的类似问题,以及为什么它们不完全是我想要做的:

这是np.where的完美用例:如果maskTrue则返回二级索引值,否则保持原样。

def replaced_with_colname(table, mask):
    data = np.where(mask, df.columns.levels[1], df)
    return pd.DataFrame(data, index=table.index, columns=table.columns)

用法:

>>> replaced_with_colname(df, df>2)
     A    B    C
   0.2  0.6  0.7
0  0.2  0.0  0.0
1  1.0  NaN  0.7
2  NaN  0.6  1.0

>>> replaced_with_colname(df, df.isna())
     A    B    C
   0.2  0.6  0.7
0  4.0  0.0  0.0
1  1.0  0.6  5.0
2  0.2  4.0  1.0

>>> replaced_with_colname(df, (0<=df) & (df<=1) | df.isna())
     A    B    C
   0.2  0.6  0.7
0  4.0  0.6  0.7
1  0.2  0.6  5.0
2  0.2  4.0  0.7

您可以使用pandas.Index.get_level_values来解决这个问题:

out = (
        df
          .gt(2)
          .mul(df.columns.get_level_values(1))
          .mask(lambda d: [d[col].eq(0) for col in d.columns])
          .combine_first(df)
      )

比较运算符( eq, ne, le, lt, ge, gt ) 等价于 ( ==, ,=, <=, <, >=, > )。

Output:

print(out)

     A    B    C
   0.2  0.6  0.7
0  0.2  0.0  0.0
1  1.0  NaN  0.7
2  NaN  0.6  1.0

如果您需要自定义 function:

def replace_with_colname(table, cond):
    out = (
            df[cond]
              .mul(df.columns.get_level_values(1))
              .mask(lambda d: [d[col].eq(0) for col in d.columns])
              .combine_first(df)
          )
    return out

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM