{"id":438,"date":"2018-07-13T08:41:22","date_gmt":"2018-07-13T06:41:22","guid":{"rendered":"http:\/\/cwiok.pl\/?p=438"},"modified":"2018-07-13T08:43:30","modified_gmt":"2018-07-13T06:43:30","slug":"kumulowanie-list-przy-uzyciu-list-accumulate","status":"publish","type":"post","link":"https:\/\/cwiok.pl\/index.php\/pl\/2018\/07\/13\/kumulowanie-list-przy-uzyciu-list-accumulate\/","title":{"rendered":"Kumulowanie list przy u\u017cyciu&#8230; List.Accumulate()"},"content":{"rendered":"<p>List.Accumulate to <strong>pot\u0119\u017cna<\/strong> funkcja, kt\u00f3ra jest cz\u0119sto pomijana podczas robienia transformacji w edytorze Power Query. Jej podstawowa funkcjonalno\u015b\u0107 jest wyt\u0142umaczona w <a href=\"https:\/\/msdn.microsoft.com\/en-us\/query-bi\/m\/list-accumulate\">dokumentacji<\/a>. Dzia\u0142a poprzez kumulowanie wynik\u00f3w zadanej operacji (<strong>accumulator function)<\/strong> zaczyn\u0105j\u0105c od warto\u015bci \u017ar\u00f3d\u0142owej i przechodz\u0105c wiersz po wierszu a\u017c do ko\u0144ca wybranej listy.<a href=\"http:\/\/radacad.com\/list-accumulate-hidden-gem-of-power-query-list-functions-in-power-bi\">Radacad<\/a> \u015bwietnie wyt\u0142umaczy\u0142 podstawowe mo\u017cliwo\u015bci tej funkcji. Ja traktuj\u0119 List.Accumulate jako funkcj\u0119, kt\u00f3ra pozwala mi dosta\u0107 si\u0119 do warto\u015bci z poprzedniego wiersza. Jest to cz\u0119sta transformacja oczekiwana przez klient\u00f3w, kt\u00f3rzy korzystaj\u0105 z Excela jako \u017ar\u00f3d\u0142a danych. 90% przypadk\u00f3w to sprawdzenie czy ID lub data ma inn\u0105 warto\u015b\u0107 ni\u017c w poprzednim wierszu.<\/p>\n<p><a href=\"http:\/\/cwiok.pl\/wp-content\/uploads\/2018\/07\/artyku\u0142_08.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-451\" src=\"http:\/\/cwiok.pl\/wp-content\/uploads\/2018\/07\/artyku\u0142_08.png\" alt=\"\" width=\"1200\" height=\"628\" srcset=\"https:\/\/cwiok.pl\/wp-content\/uploads\/2018\/07\/artyku\u0142_08.png 1200w, https:\/\/cwiok.pl\/wp-content\/uploads\/2018\/07\/artyku\u0142_08-300x157.png 300w, https:\/\/cwiok.pl\/wp-content\/uploads\/2018\/07\/artyku\u0142_08-768x402.png 768w, https:\/\/cwiok.pl\/wp-content\/uploads\/2018\/07\/artyku\u0142_08-1024x536.png 1024w\" sizes=\"auto, (max-width: 1200px) 100vw, 1200px\" \/><\/a><\/p>\n<p>Ale jak to zrobi\u0107? Przyk\u0142ady Radaca&#8217;a s\u0105 super, ale chcia\u0142bym kumulowa\u0107 listy!<\/p>\n<p>Zapoznajmy si\u0119 ze sk\u0142adn\u0105 na podstawie prostego przyk\u0142adu skumulowanej sumy. W tym wypadku mam prost\u0105 tabel\u0119 z liczbami od 1 do 10.<\/p>\n<p><a href=\"http:\/\/cwiok.pl\/wp-content\/uploads\/2018\/07\/image.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-420\" src=\"http:\/\/cwiok.pl\/wp-content\/uploads\/2018\/07\/image.png\" alt=\"\" width=\"181\" height=\"267\" \/><\/a><\/p>\n<p>Aby stworzy\u0107 list\u0119 ze skumulowan\u0105 sum\u0105 przy u\u017cyciu List.Accumulate(), wpisuj\u0119:<\/p>\n<pre class=\"toolbar:2 wrap:true scroll:true lang:default decode:true\">Cumulative_new  = List.Accumulate(#\"Changed Type\"[Values],{0}, (sum,index) =&gt;  if index = #\"Changed Type\"[Values]{0} then {#\"Changed Type\"[Values]{0}} else sum&amp; {List.Last(sum) + index})<\/pre>\n<p>Wynikiem jest lista ze skumulowanymi warto\u015bciami:<\/p>\n<p><a href=\"http:\/\/cwiok.pl\/wp-content\/uploads\/2018\/07\/image-1.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-422\" src=\"http:\/\/cwiok.pl\/wp-content\/uploads\/2018\/07\/image-1.png\" alt=\"\" width=\"128\" height=\"266\" \/><\/a><\/p>\n<p>Przejd\u017amy przez sk\u0142adni\u0119:<\/p>\n<pre class=\"toolbar:2 wrap:true scroll:true lang:default decode:true\">List.Accumulate(#\"Changed Type\"[Values],{0}, (sum,index) =&gt;  if index = #\"Changed Type\"[Values]{0} then {#\"Changed Type\"[Values]{0}} else sum&amp; {List.Last(sum) + index})\r\n\r\n<\/pre>\n<p>Pierwszy argument wskazuje na list\u0119, przez kt\u00f3r\u0105 b\u0119dziemy iterowa\u0107. W naszym wypadku jest to jedna kolumna:<\/p>\n<pre class=\"toolbar:2 wrap:true scroll:true lang:default decode:true\">#\"Changed Type\"[Values]<\/pre>\n<p>Drugim argumentem jest warto\u015b\u0107 \u017ar\u00f3d\u0142owa &#8211; seed. W naszym wypadku {0} &#8211; czyli lista maj\u0105ca jeden element 0:<\/p>\n<pre class=\"toolbar:2 wrap:true scroll:true lang:default decode:true\">{0}<\/pre>\n<p>Trzecim argumentem jest operacja &#8211; accumulator function:<\/p>\n<pre class=\"toolbar:2 wrap:true scroll:true lang:default decode:true\">(sum,index) =&gt;  if index = #\"Changed Type\"[Values]{0} then {index} else sum&amp; {List.Last(sum) + index})<\/pre>\n<p>Dla wyja\u015bnienia: index &#8211; tutaj oznacza warto\u015b\u0107 w wierszu w jakim &#8220;znajduje si\u0119&#8221; funkcja, sum &#8211; to wynik operacji. Te nazwy mo\u017cna dowolnie modyfikowa\u0107.<\/p>\n<p>Je\u015bli index jest r\u00f3wna pierwszej warto\u015bci z listy, accumulator przyjmie warto\u015b\u0107 {index} &#8211; czyli lista z index. Poni\u017csza linijka jest bardzo wa\u017cna, poniewa\u017c nie chcemy warto\u015bci \u017ar\u00f3d\u0142owej jak pierwszej. Nie mo\u017cemy te\u017c zmieni\u0107 seed&#8217;a na pierwsz\u0105 warto\u015b\u0107 w li\u015bcie, poniewa\u017c accumulator b\u0119dzie chcia\u0142 doda\u0107 seed to tej pierwszej warto\u015bci, dubluj\u0105c j\u0105.<\/p>\n<pre class=\"toolbar:2 wrap:true scroll:true lang:default decode:true\">if index = #\"Changed Type\"[Values]{0} then {index}<\/pre>\n<p>Poni\u017cszy kod oznacza: Je\u015bli index nie jest pierwsz\u0105 warto\u015bci\u0105 listy, chcia\u0142bym do\u0142\u0105czy\u0107 do wyniku accumulatora (w drugim kroku b\u0119dzie to {1}), list\u0119, kt\u00f3ra ma warto\u015b\u0107 List.Last(sum) + index. List.Last(sum) + index oznacza, \u017ce wezm\u0119 ostatni element wyniku accumulatora i dodam do niego index. To zwr\u00f3ci mi list\u0119 z jednym elementem np. {3}, kt\u00f3r\u0105 dodam do wyniku otrzymuj\u0105c {1,3}. Po powt\u00f3rzeniu krok\u00f3w 10 razy otrzymam skumulowane sumy.<\/p>\n<pre class=\"toolbar:2 wrap:true scroll:true lang:default decode:true\">else sum&amp; {List.Last(sum) + index})<\/pre>\n<p>Ostatnim krokiem jest po\u0142\u0105czenie tabeli i stworzonej listy:<\/p>\n<pre class=\"toolbar:2 wrap:true scroll:true lang:default decode:true\">#\"Converted to Table\" = Table.FromList(Cumulative_new, Splitter.SplitByNothing(), null, null, ExtraValues.Error),    \r\n\/\/I merge two columns into a table\r\nAdd_columns= Table.FromColumns(Table.ToColumns( #\"Changed Type\")&amp;{Cumulative_new})<\/pre>\n<p><a href=\"http:\/\/cwiok.pl\/wp-content\/uploads\/2018\/07\/image-2.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-424\" src=\"http:\/\/cwiok.pl\/wp-content\/uploads\/2018\/07\/image-2.png\" alt=\"\" width=\"320\" height=\"298\" srcset=\"https:\/\/cwiok.pl\/wp-content\/uploads\/2018\/07\/image-2.png 320w, https:\/\/cwiok.pl\/wp-content\/uploads\/2018\/07\/image-2-300x279.png 300w\" sizes=\"auto, (max-width: 320px) 100vw, 320px\" \/><\/a><\/p>\n<p>Ca\u0142y kod:<\/p>\n<pre class=\"toolbar:2 wrap:true scroll:true lang:default decode:true\" title=\"Whole code\">let\r\n     Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText(\"i45WMlSK1YlWMgKTxmDSBEyagkkzMGkOJi3ApCWYNDRQio0FAA==\", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type text) meta [Serialized.Text = true]) in type table [Values = _t]),\r\n     #\"Changed Type\" = Table.TransformColumnTypes(Source,{{\"Values\", Int64.Type}}),\r\n      Cumulative_new  = List.Accumulate(#\"Changed Type\"[Values],{0}, (sum,index) =&gt;  if index = 1 then {index} else sum&amp; {List.Last(sum) + index}),\r\n      #\"Converted to Table\" = Table.FromList(Cumulative_new, Splitter.SplitByNothing(), null, null, ExtraValues.Error),\r\n  Cumulative_new_new  = List.Accumulate(#\"Changed Type\"[Values], {0}, (sum,index) =&gt;   sum&amp;{ index}),\r\n     \r\n     \/\/I merge two columns into a table\r\n     Add_columns= Table.FromColumns(Table.ToColumns( #\"Changed Type\")&amp;{Cumulative_new})\r\n   \r\nin\r\n     Add_columns<\/pre>\n<p><a href=\"https:\/\/community.powerbi.com\/t5\/Desktop\/Adding-conditional-index-based-on-changing-field-in-Power-Query\/m-p\/436951\/highlight\/true#M201532\">Inny przyk\u0142ad<\/a> jest prosto z forum Power BI. Zadanie jest proste &#8211; stworzy\u0107 specjalny indeks, kt\u00f3ry wzrasta gdy warto\u015b\u0107 w kolumnie Product si\u0119 zmienia:<\/p>\n<p><a href=\"http:\/\/cwiok.pl\/wp-content\/uploads\/2018\/07\/image-3.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-434 size-full\" src=\"http:\/\/cwiok.pl\/wp-content\/uploads\/2018\/07\/image-3.png\" alt=\"\" width=\"264\" height=\"300\" \/><\/a><\/p>\n<p>Kod mojego rozwi\u0105zania:<\/p>\n<pre class=\"toolbar:2 wrap:true scroll:true lang:default decode:true\" title=\"Solution from the forum\">let\r\n     Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText(\"i45WclSK1UElPTFIRxxsuEgsAA==\", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type text) meta [Serialized.Text = true]) in type table [Category = _t]),\r\n     #\"Changed Type\" = Table.TransformColumnTypes(Source,{{\"Category\", type text}}),\r\n     #\"Added Index\" = Table.AddIndexColumn(#\"Changed Type\", \"Index\", 0, 1),\r\n    \r\n     New_app = List.Accumulate(#\"Added Index\"[Index],{0}, (state,current) =&gt;  if current = 0 then {1} else if #\"Added Index\"{current-1}[Category] = #\"Added Index\"{current}[Category] then state &amp; {List.Last(state)} else state &amp; {List.Last(state)+1}),\r\n     Add_columns= Table.FromColumns(Table.ToColumns(#\"Added Index\")&amp;{New_app}),\r\n    \r\n     #\"Removed Columns1\" = Table.RemoveColumns(Add_columns,{\"Column2\"}),\r\n     #\"Renamed Columns\" = Table.RenameColumns(#\"Removed Columns1\",{{\"Column1\", \"Product\"}, {\"Column3\", \"Index\"}})\r\nin\r\n     #\"Renamed Columns\"<\/pre>\n<p>Warto zwr\u00f3ci\u0107 uwag\u0119 na lini\u0119:<\/p>\n<pre class=\"toolbar:2 wrap:true scroll:true lang:default decode:true \">New_app = List.Accumulate(#\"Added Index\"[Index],{0}, (state,current) =&gt;  if current = 0 then {1} else if #\"Added Index\"{current-1}[Category] = #\"Added Index\"{current}[Category] then state &amp; {List.Last(state)} else state &amp; {List.Last(state)+1}),<\/pre>\n<p>Jest bardzo podobna do poprzedniego przyk\u0142adu. Jedyna zmiana to warunek &#8220;if else&#8221;, kt\u00f3ry sprawdza wyra\u017cenie:<\/p>\n<pre class=\"toolbar:2 wrap:true scroll:true lang:default decode:true\">#\"Added Index\"{current-1}[Category] = #\"Added Index\"{current}[Category]<\/pre>\n<p>W tym wypadku iterujemy przez kolumn\u0119 z indeksem. Powy\u017csza linia sprawdza czy warto\u015bci w kolumnie Category w tym i poprzednim wierszu s\u0105 takie same. Je\u015bli tak, to accumulator do\u0142\u0105cza do listy jej ostatni element:<\/p>\n<pre class=\"toolbar:2 wrap:true scroll:true lang:default decode:true\">state &amp; {List.Last(state)}<\/pre>\n<p>W przeciwym wypadku dodaje 1 do ostatniej warto\u015bci:<\/p>\n<pre class=\"toolbar:2 wrap:true scroll:true lang:default decode:true\">state &amp; {List.Last(state)+1}),<\/pre>\n<p><a href=\"https:\/\/community.powerbi.com\/t5\/Desktop\/Repeat-last-date-for-each-row\/m-p\/441429\/highlight\/true#M203838\">Tutaj<\/a> m\u00f3j jeszcze jeden przyk\u0142ad z forum.<\/p>\n<p>I to wszystko! Dajcie zna\u0107 co my\u015blicie o tym podej\u015bciu do List.Accumulate()!<\/p>\n<p>Dzi\u0119ki!<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>List.Accumulate to <strong>pot\u0119\u017cna<\/strong> funkcja, kt\u00f3ra jest cz\u0119sto pomijana podczas robienia transformacji w edytorze Power Query. Jej podstawowa funkcjonalno\u015b\u0107 jest wyt\u0142umaczona w <a href=\"https:\/\/msdn.microsoft.com\/en-us\/query-bi\/m\/list-accumulate\">dokumentacji<\/a>. Dzia\u0142a poprzez kumulowanie wynik\u00f3w zadanej operacji (<strong>accumulator function)<\/strong> zaczyn\u0105j\u0105c od warto\u015bci \u017ar\u00f3d\u0142owej i przechodz\u0105c wiersz po wierszu a\u017c do ko\u0144ca wybranej listy.<a href=\"http:\/\/radacad.com\/list-accumulate-hidden-gem-of-power-query-list-functions-in-power-bi\">Radacad<\/a> \u015bwietnie wyt\u0142umaczy\u0142 podstawowe mo\u017cliwo\u015bci tej funkcji. Ja traktuj\u0119 List.Accumulate jako funkcj\u0119, kt\u00f3ra pozwala mi dosta\u0107 si\u0119 do warto\u015bci z poprzedniego wiersza. Jest to cz\u0119sta transformacja oczekiwana przez klient\u00f3w, kt\u00f3rzy korzystaj\u0105 z Excela jako \u017ar\u00f3d\u0142a danych. 90% przypadk\u00f3w to sprawdzenie czy ID lub data ma inn\u0105 warto\u015b\u0107 ni\u017c w poprzednim wierszu.<\/p>\n<p><a href=\"http:\/\/cwiok.pl\/wp-content\/uploads\/2018\/07\/artyku\u0142_08.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-451\" src=\"http:\/\/cwiok.pl\/wp-content\/uploads\/2018\/07\/artyku\u0142_08.png\" alt=\"\" width=\"1200\" height=\"628\" srcset=\"https:\/\/cwiok.pl\/wp-content\/uploads\/2018\/07\/artyku\u0142_08.png 1200w, https:\/\/cwiok.pl\/wp-content\/uploads\/2018\/07\/artyku\u0142_08-300x157.png 300w, https:\/\/cwiok.pl\/wp-content\/uploads\/2018\/07\/artyku\u0142_08-768x402.png 768w, https:\/\/cwiok.pl\/wp-content\/uploads\/2018\/07\/artyku\u0142_08-1024x536.png 1024w\" sizes=\"auto, (max-width: 1200px) 100vw, 1200px\" \/><\/a><\/p>\n<div class=\"tech_read_more\"><a href=\"https:\/\/cwiok.pl\/index.php\/pl\/2018\/07\/13\/kumulowanie-list-przy-uzyciu-list-accumulate\/\">Read More<\/a><\/div>","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[44],"tags":[],"class_list":["post-438","post","type-post","status-publish","format-standard","hentry","category-power-query-pl"],"_links":{"self":[{"href":"https:\/\/cwiok.pl\/index.php\/wp-json\/wp\/v2\/posts\/438","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/cwiok.pl\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/cwiok.pl\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/cwiok.pl\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/cwiok.pl\/index.php\/wp-json\/wp\/v2\/comments?post=438"}],"version-history":[{"count":0,"href":"https:\/\/cwiok.pl\/index.php\/wp-json\/wp\/v2\/posts\/438\/revisions"}],"wp:attachment":[{"href":"https:\/\/cwiok.pl\/index.php\/wp-json\/wp\/v2\/media?parent=438"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/cwiok.pl\/index.php\/wp-json\/wp\/v2\/categories?post=438"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/cwiok.pl\/index.php\/wp-json\/wp\/v2\/tags?post=438"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}