|
回复一个两年前的问题,不知道楼主是否能看到。
实际上Table.ReplaceValue函数的标准格式是要求比较明确的
=Table.ReplaceValue(table,old value,new value,Replacer函数, {"要查找的column名"(这里可以多列,需要逗号分开用大括弧整体括在外面作为一个list}) )
所以原来那句= Table.ReplaceValue(源,12,each [A],Replacer.ReplaceValue,{"B"})
就是:在B列中,查所有oldvalue=12的,把它替换为 当前行(each 上下文就变成B列的逐行)中的列A内的内容(newvalue)。
而你想实现的【如果A列为Y,则把B列替换为100】= Table.ReplaceValue(源,each [A]="Y",100,Replacer.ReplaceValue,{"B"})为什么没有效果呢?
这是因为如果按照你的要求,PQ会理解为,你要在B列中,查找的oldvalue是 each [A]="Y' 而不是 "Y",也不是去查找A列是否等于Y。
这句有点绕,但实际上你理解为它要先去判断 [A]="Y"这个表达式的值,而这是一个逻辑判断,值就只有TRUE or FALSE。
然而在B列中并没有这样两个逻辑值的存在,所以找不到这个oldValue,自然就无法触发替换动作了。
这个假设可以通过构造一个C列,来验证:=Table.AddColumn(源,"C", each if [A]="Y" then true else false, type logical )
这时候表格如下
A | B | C | Y | 12 | TRUE | N | 32 | FALSE |
这时候再加一句:= Table.ReplaceValue(已添加自定义,each [A]="Y",100,(x,y,z)=>if y then z else y,{"C"})
就会发现C的第一行的TRUE被成功替换成100了。第二行则保持不动,因为FALSE不符合 A=100的条件判断。
A | B | C | Y | 12 | 100 | N | 32 | FALSE
|
需要注意的是,这里Replacer.ReplaceValue函数被我用自定义三参函数 (x,y,z) 替换。
所有PQ函数里的子函数 如果有特定的参数要求的时候,都可以被同样的参数数量的自定义函数替换。(可以研究一下splitter/combiner/replacer这几个系列)
当你把(x,y,z)改回Replacer.ReplaceValue的时候,就会发现 C列下的100和FALSE都被替换成了100。答案也是很显然的,因为在原版replacer函数这里,是直接对x这个值里去查找y并且替换成z。如果我们构造的C列本身是TRUE和FALSE两行的值,而[A]="Y"的判断在第一行也就是TRUE,第二行也就是FALSE。所以就等于 if x=y then z,所以两行都会被替换成100。
总结:
1. 错误写法:= Table.ReplaceValue(源,each [A]="Y",100,Replacer.ReplaceValue,{"B"})
2. 正确写法:= Table.ReplaceValue(源,each [A]="Y",100,(x,y,z)=>if y then z else x,{"B"})
直接使用Replacer函数时,y在前面的写法会输出逻辑值true/false,而B列中并不存在,所以查不到,不会触发替换。
需要改成自定义三参,使用条件判断 if y (=true or false)来进一步指定B列(x)被赋值为z(100),或者不动,还是B列原值。
|
评分
-
2
查看全部评分
-
|