Zapętlenie zapytania internetowego po wierszach w tabeli w Power BI
Jako nowozatrudniony Datanauta w Clouds on Mars pracuję z Power BI każdego dnia. Moje pierwsze, krótkie zadanie polegało na wsparciu klienta przy łączeniu się z API w Power BI. Pilotażowy raport był połączony tylko z jedną stroną internetową. Klient wymagał natomiast, żeby raport pobierał dane z wielu różnych stron. Dodatkowo, lista stron powiększała się w czasie (była również jednym z zapytań API). Z technicznego punktu widzenia wymagało to iteracji po elementach ID w tabeli i łączeniu się z nowym adresem URL z kolejnym ID. Była to dobra okazja do wykorzystania języka M. W M nie ma funkcji pętli, więc musiałem obejść ten problem.
Żeby pokazać moje rozwiązanie tego problemu użyję przykładu – danych pogodowych z kilku miast w Polsce. URL wygląda tak:
https://danepubliczne.imgw.pl/api/data/synop/station/jeleniagora
Mam na celu pobranie danych z 7 miast, które umieściłem w tabeli Cities:
City
jeleniagora
warszawa
szczecin
koszalin
lublin
katowice
legnica
Pobranie danych manualnie wymagałoby importu z 7 stron, a następnie połączenie ich. Wykonalne. Natomiast, pobranie danych dla 100 miast lub listy miast, która się zmienia, byłoby znacznie trudniejsze. Dla przejrzystości podzieliłem cały proces na kilka następujących kroków:
- Pierwszy krok polega na pobraniu danych dla jednego z miast i wykonaniu wszystkich transformacji. Można użyć funkcji dostępnych domyślnie i nie trzeba wykorzystywać języka M. Po pobraniu danych, otrzymuję tabelę:
Naturalnie, żeby dane były łatwiejsze do złączenia z danymi dla pozostałych miast, wykonuję operację Pivot i zmieniam nazwy kolumn.
Drugi krok to stworzenie funkcji, która przyjmuje nazwę miasta jako parametr i zwraca tabelę podobną do tej wyżej. Jest to możliwe za pomocą interfejsu Power BI, ale skupię się na języku M i edytorze zapytań:
Skrypt poniżej pokazuje proces transformacji z pierwszym miastem – Jelenią Górą. Muszę zmodyfikować skrypt i zmienić nazwę miasta na parametr. To pozwoli mi pobierać dane z różnych stron przy każdym wywołaniu funkcji.
Aby stworzyć funkcję muszę najpierw zadeklarować parametr – city – używając frazy: “(city as text) =>” na początku skryptu. Następnie, zamieniam “jeleniagora” na parametr city i łączę je używając znaku & – zupełnie jak w Excelu. Gotowy skrypt wygląda tak:
Jest on bardzo podobny do skryptu z pierwszej tabeli. Zmieniam nazwę na get_weather. Mogę wywołać funkcję poprzez wpisanie parametru.
Trzeci krok polega na wywołaniu funkcji get_weather dla każdego z miast w jednej tabeli. Wybieram puste zapytanie i wpisuje skrypt taki jak poniżej:
City_names daje mi listę miast, dla których chcę otrzymać dane pogodowe. Poprzez użycie funkcji List.Transform(city_names, each get_weather(_)) Power BI wywołuje funkcję dla każdego z miast na liście i skleja odpowiedzi w listę. Wynik transformacji powinien wyglądać tak:
Aby otrzymać dane muszę przekonwertować listę na tabelę:
A następnie ją rozwinąć:
To daje mi tabelę z danymi dla każdego z miast:
To podejście można zastosować również dla innych źródeł danych. Ważną informacją do zapamiętania jest możliwość iteracji po elementach w liście za pomocą funkcji List.Transform(). Jeśli znacie inne sposoby, proszę podzielcie się z nimi!
Dzięki,
Michał