Forum Discussion
Power Query - Table.ReplaceValue - Behavior ?
- 1 year ago
Sur les points 1 et 3
quand vous ajoutez une colonne à une table, vous ne vous demandez pas ce que veut dire le [xxxx]
exemple, si vous créez une nouvelle colonne avec les 2 derniers caractères d'une autre colonne
= Table.AddColumn(Source, "Column2", each Text.End([Column1], 2), type text)
le [Column1] désigne le texte contenu dans le champ intitulé "Column1" de votre ligne en cours
cela vous semble naturel !
vous pourriez également écrire :
= Table.AddColumn(Source, "Column2", (_) => Text.End(_[Column1], 2), type text)
ici j'ai mis un _ mais vous auriez pu mettre un x ou informer
cette syntaxe est valable
= Table.AddColumn(Source, "Column2", (informer) => Text.End(informer[Column1], 2), type text)
il est implicite que "informer" est l'enregistrement en cours (de l'étape "source")
La fonction Table.ReplaceValue est plus complexe car la fonction du 4e argument utilise les 3 arguments précédents pour elle-même. quelque soit les noms qu'on leur donne (x,y,z) ou (a,b,c) ou (informer1,informer2,informer3)
= Table.ReplaceValue(Source, Argument2, Argument3, (informer1,informer2,informer3)=>informer2, {"Column1"}ici on remplacera la column1 par le valeur du 2e argument
ce peut être du texte, un nombre, une liste... lié à la ligne en cours si on a un each...
mais également une valeur d'une autre requête
un exemple tiré par les cheveux pour bien comprendre,
let
Source = Table.FromColumns({{1..3}},{"Column1"}),
Replace = Table.ReplaceValue(Source, Source[Column1], (toto)=> Source , (a,b,c)=>a, {"Column1"})
in
Replacene changera rien à la column1, on prend la valeur du premier argument (donc la column1) et on le remet.
let
Source = Table.FromColumns({{1..3}},{"Column1"}),
Replace = Table.ReplaceValue(Source, Source[Column1], (toto)=> Source , (a,b,c)=>b, {"Column1"})
in
Replaceon n'a pas de each, on n'est donc pas dans la ligne en cours, on prendre la colonne "Column1" de la table "Source" c'est à dire la colonne elle-même (en entier !)
on aura donc une liste {1..3} dans chaque cellule.
enfin,
let
Source = Table.FromColumns({{1..3}},{"Column1"}),
Replace = Table.ReplaceValue(Source, Source[Column1], (toto)=> Source , (a,b,c)=>c, {"Column1"})
in
Replaceici la fonction renvoie c, le 3eme argument que j'ai volontairement écrit (toto)=> (toto ou _ ou each, c'est la même chose, c'est la ligne en cours
sauf que là, je ne renvoie pas un champ spécifique de la ligne avec des [ ] mais Source, donc l'étape précédente.
Dans toutes les cellules j'aurais donc la table Source avec sa seule colonne de trois valeurs, 1, 2, 3.
Quant au point 2, Power Query ne génère pas d'erreur lorsqu'il n'y a pas assez d'argument, mais les modifications ne sont pas effectuées
Si par exemple j'écris := Table.ReplaceValue(Source, each null, each null , Date.Day, {"Column1"})Date.Day est une fonction avec un seul argument, je n'ai aucune erreur, mais la fonction ne remplace rien.
= Table.ReplaceValue(Source, each null, each null , List.Accumulate, {"Column1"})pas d'erreur non plus avec List.Alternate qui demande pourtant 3 arguments. la fonction renvoie un erreur, il ne se passe rien. peut-être un bug de Power Query ?
Est-ce plus clair ?
Stéphane
informer lets start from your last questions:
# 3 mandatory parameters for custom replacer: it's because Table.ReplaceValue passes all 3 to this function.
# assiciations: look at any standard PQ replacer function definition:
Replacer.ReplaceValue(value as any, old as any, new as any) as any
Arguments' values are passed in the same order. So that
value : current value in one of columnsToSearch
old: oldValue in Table.ReplaceValue
new: newValue in Table.ReplaceValue
Keeping the above in mind try to imagine what's going on in your use cases: column by column, row by row...
- informer1 year ago
Helper I
Thanks for your help
The 4th parameter is a function
I don't understant the 2nd exemple because it's a personal function and Replacer.ReplaceValue is never called
(curval,oldval, newval)=> newval,In the example below, Replacer.ReplaceValue is not called
= Table.ReplaceValue( Source, each [Acronyme], null, (x,y,z) => List.Accumulate( List.Reverse(Text.PositionOf(x, y, Occurrence.All, Comparer.OrdinalIgnoreCase)), x, (s,c)=>Text.RemoveRange(s, c, Text.Length(y))), {"Nom", "Volume", "Circulating Supply"})In the Table.ReplaceValue, nothing is precised about parameters to pass in
replacer as function,
I'm sure I'm missing something about construction of a personal function !!!
- AlienSx1 year ago
Super User
what's so special about Replacer.ReplaceValue? It's one of many other functions in M. You may use any other custom function with the same list of agruments. All you need to now is that Table.ReplaceValue passes exactly 3 values into it's 4th argument (the function we are talking about). By "passes" I mean that Table.ReplaceValue calls that function like we call any other function in M. Back to your examples:
1. The one with Replacer.ReplaceValue: full syntax of this "replacer" is
Replacer.ReplaceValue(value as any, old as any, new as any) as anyand basically it compares value with old and if value = old then it replaces value with new. Your "old" argument always has a value of kidhome field. And when Table.ReplaceValue works with "kidhome" column then value is always equal to old. That's why kidhome column = 2 (as you defined new) after transformation.
When working with teenhome field, it's value will be replaced by 2 only when [teenhome] = [kidhome] (or when value = old). That's why replacements are made in rows 1 through 4 and 8.
2. The one with custom function: here your custom function always returns a value of new with is 2 in your case - without regard of any other values in any other column. That's why both column's values got replaced with 2.
Table.ReplaceValue is not easy to understand and I feel your frustration. Good luck!
- informer1 year ago
Helper I
Thanks AlienSx for your help.
Does (x,y,z) =>mean that the Replacer function is called and applies the code after () => so in a way a new dynamics function is declared and called (=> Repalcer.Newfunction) ?
If it's so it's the one great step for ma undestanding of
(x,y,z) =>
Is it the M langage philosphy to assign implictly to the function parameters, the objects declare above the function ?