[英]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 < 2
、 df >= 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
的完美用例:如果mask
为True
则返回二级索引值,否则保持原样。
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.