Temat: Współpraca .NET i R - biblioteka dla systemów analitycznych.

Gdyby ktoś miał ochotę skrobnąć coś, co korzysta z R na platformie .NET, to służę pomocą na temat pracy z biblioteką RDCOM.

Co prawda kończy mi się pracowity urlop, ale spróbuję na dniach opisać tutaj projekt, którym zajmowałem się jakiś czas - spory system klas proxy (opakowujących, pośredniczących) dla celów stworzenia online'owego systemu analiz statystycznych, wykorzystującego R.

Chodziło o to, aby napisać swego rodzaju framework (.NET / C#), pozwalający pracować z R z poziomu kodu programu.

Dzięki stworzeniu odpowiedniej liczby klas dla źródeł danych (providery danych), selektorów danych, klas testów statystycznych (poukładane ładnie w przestrzeniach nazw) i tak dalej dało się z tego poukładać, jak z cegiełek jakiś tam scenariusz podstawowej analizy statystycznej.

Oczywiście każdy test statystyczny i procedura umie się sama opisać . Zarówno przez klasę wynikową (oraz klasy kolekcji), jak i przez zapis specjalnymi formatterami: do XML, do HTML (dostarczam
podstawowy formatter), a także - do tablicy stringów z wynikami analiz (otrzymuje się coś na kształt "tekstowego raportu").

Potem dorabiało się interfejs w ASP.NET - wybór zmiennej/zmiennych, okreslanie dziedziny (sql'owe "where / having") i pisało odpowiedni formater danych, korzystający z arkuszy CSS.

Niestety, jak to bywa w projektach tworzonych "na szybko", nie mam dokumentacji (czytaj - jestem jedyną instancją dokumentacji :) ), tę trzeba napisać. Chociaż wydaje mi się, że wystarczy diagram UML i seria przykładów ("learn by examples"). Inaczej musiałbym spędzić kolejne 3 urlopy przy tym :)

Oczywiście jestem autorem kodu, a w umowie z firmą, dla której to pisałem, jest zawarta klauzula o posiadaniu przeze mnie praw autorskich i majątkowych do kodu, a także o tym, że mogę ten kod dowolnie rozpowszechniać i sprzedawać. I na podobnej licencji umieszczę tutaj ten kod. Być może będzie to licencja LGPL - musiałbym się wgłębić w szczegóły licencyjne, a nie mam głowy na razie do tego.

System domyślnie współpracował z relacyjnymi bazami danych (SQL Server), w których trzymane były dane z badań klinicznych. Dlatego starałem się, aby można było podawać "selekty", których wynikiem jest układ rekordowy (np. wyniki kolejnych miesięcy terapii w kolejnych wierszach) jak i kolumnowy (kolejnie miesiące terapii w osobnych kolumnach).

Dostęp do danych załatwia ADO.NET jak również biblioteka RDOBC - przetestowana przeze mnie i w pełni przydatna w tym projekcie.

Optymalizacje - nie było czasu myśleć o takich "szczegółach", system spełniał swoje zadanie dostatecznie dobrze w takiej postaci, w jakiej został napisany.

Przykładowy scenariusz, jaki da się zrealizować w bieżącej postaci biblioteki:

Dane wejściowe:
"DataSet" (rekordset, zbiór danych - dla programistów pojęcie to powinno być czytelne: zestaw tabel wynikowych, powiązanych relacjami) będący wynikiem odpowiedniego zapytania do bazy danych.

Tabele datasetu mogą być w postaci:
- "stacked" (2 kolumny: wartość zmiennej, czynnik grupujący)
- kolumnowej; kolejne wartości atrybutu w kolejnych kolumnach, np. wyniki pomiarów hematokrytu w kolejnych miesiącach terapii znajdują się w kolejnych kolumnach tabeli.

Braki danych reprezentowane są przez "erowe" NA, a po stronie .NET - przez Double.NaN

1. Przygotowanie tabel z wynikami badań (kwerendy SQL) oraz wczytanie ich do środowiska "R". W międzyczasie następuje "tłumaczenie" zawartości obiektu DataTable na obiekt matrix R.

UWAGA: tabele mogą mieć, w tej wersji, zawartość JEDYNIE liczbową!
Żadnych literałów!

Jeśli w tabelach są literały, mozna pozamieniać je na liczby jeszcze w kwerendzie wybierającej (select), np. tak:

Obrazek


a najlepiej utworzyć nową tabelę ze skonwertowanymi danymi:

Obrazek


2. Przygotowanie selektorów danych (która tabela, która kolumna/y)
3. Sprawdzenie, czy zmienne reprezentowane selektorem mają rozkłady normalne (na razie mam tylko klasę dla testu Shapiro-Wilka, ale chyba pisałem też klasę i funkcje "R" dla testu Jarque-Bera)
4. Jeśli rozkład chociaż jednej zmiennej nie jest normalny, transformacja zmiennych jedną z funkcji (asin, sqrt, kwadrat, szescian, odwrotnosc, log, exp). Dodatkowo ciągle badana jest homogeniczność wariancji zmiennych (test Levena)
5. Jeśli żadna z transformacji nie znormalizowała rozkładu, przejście do analiz nieparametrycznych.
6. Jeśli udało się znaleźć transformatę normalizującą (pierwsza z brzegu), to dalej będzie ona używana w programie. Trzeba o tym pamiętać przy podawaniu wyników statystyk opisowych!
7. Przeprowadzane są testy "omnibus": parametryczna lub nieparametryczna, dla prób zależnych bądź niezależnych ANOVA.
8. Jeśli wynik wskaże istnienie co najmniej jednej statystycznie istotnej różnicy między zmiennymi, przeprowadzane są testy post-factum (parametryczne bądź nieparametryczne). Oczywiście każdy zaprogramuje sobie test, jakiego potrzebuje... MSD, LSD, Tukeya, t-Studenta z poprawką Bonferroniego...

Dostepne są także klasy prostych testów dla 2 prób: parametryczne, nieparametryczne, dla prób zależnych i niezależnych. Jest test korelacji i regresji liniowej wraz z istotnościami współczynników.

Oczywiście nie znajdziecie tutaj wszystkich znanych Wam testów. Nie znajdziecie ich wielu, bo po prostu nie były mi potrzebne (np. testu chi2 - trzeba sobie napisać własną klasę).

Pisanie klas testów i procedur polega na tym, że dziedziczy się po odpowiedniej klasie testu statystycznego i "zaszywa" w niej listę poleceń R. Literał ten podaje się jako argument do metody, przekazującej go z kolei, przez DCOM, do środowiska R.
Trzeba też przygotować odpowiednią klasę wynikową, czyli odczytać wyniki z tablic, zwracanych przez "R" i "powkładać" je w odpowiednie pola klasy wynikowej.

Ma to wielką wadę - jeśli kiedyś, ktoś, nie bacząc na standardy, pozmienia coś w strukturze obiektu zwrotnego R (np. zamiast p.val będzie zmienna pvalue), to nasz analizator "się sypnie".

Niestety, rozwiązanie nie jest proste. Należałoby mieć pliki konfiguracyjne (lub zapis w bazie danych), w których podawałoby się co i jak zwraca określona funkcja "R", a następnie trzeba by brać to pod uwagę w kodzie. Niestety - nie mam ani czasu, ani większej ochoty tworzyć kolejnego "kombajnu"... może kiedyś :)

Jesli to, co napisałem, zainteresuje jakiegoś statystyka-programistę, proszę o informację. A to dlatego, że już od paru miesięcy nie mogę się zmoblilizować, aby opisać to, co stworzyłem kiedyś... Wielu było zainteresowanych, ale tylko tak "pobieżnie". Jeśli kogoś zainteresuje taka biblioteka na poważnie - wówczas wyłożę jeszcze swój czas.

Być może przyda się to komuś, kto:
1. potrzebuje "silnika obliczeń" R w swoim projekcie pisanym na platformie .NET
2. pisze środowisko graficzne dla tego języka

Dla Unixów jest fajna biblioteka komunikująca się z R poprzez TCP/IP. Jest szybka i zoptymalizowana, na pewno lepsza, niż moje dzieło. Na Windows także działa, ale nie zapewnia wielosesyjności.
Niestety, póki jakiś zapaleniec nie napisze tego co ja, tylko lepiej - nie będzie zbyt wielu alternatyw :)

Niestety, moja bibliteka potrafi jeszcze wyrzucać wyjątki. Spowodowane jest to, że czasem biblioteka RDCOM dla jednego wywołania zwraca wynik o typie double[,] a czasem object[,]

Spowodowane jest to tym, że jeśli R zwrócił NA, to jest to literał ("object"), a jesli liczbę - to double. Nie wszędzie jeszcze mam to obsłużone. Zwykle wystarczyło odpowiednio dopracować zapytanie "R" :)

---------------------------------
Przykład zastosowania.

Otóż pisałem ja swego czasu system automatycznych (i jedynie bardzo ogólnych - wszak nic nie zastąpi człowieka w analizie danych) analiz dla medycznych programów naukowych.

Wyglądało to tak, że był sobie serwis www poświęcony konkretnemu programowi medycznemu. W jego skład wchodziły następujące moduły:
- elektroniczna wersja CRFa, wraz z walidacją, kreatorem wprowadzania danych oraz wyszukiwarką, etc.
- panel statystyczno-administracyjny oferujący podsumowanie realizacji programu (ile ośrodków, ilu lekarzy, ile pacjentów, ile miesięcy, etapów terapii w którym ośrodku, etc)
- panel "szybkich" analiz statystycznych.

W tym ostatnim chodziło o to, aby lekarze-badacze, zanim jeszcze zlecą konkretne analizy (cóż, pomarzyć można było o eksperymencie przygotowanym pod przyszłe analizy :) ), jeszcze w trakcie badania mieli pogląd na to, co się w nim dzieje.

Przygotowywali zatem pewne zestawy analiz, których wyniki chcieli śledzić.

Nie interesowały ich dokładne wyniki, a także cały proces wnioskowania. Chodziło o prostotę. Wybierali z listy analizę "Odpowiedź organizmu na XXXX w kolejnych miesiącach terapii" i po chwili mieli wykres, trend oraz tabelkę istotności różnic pomiędzy kolejnymi miesiącami terapii.

Dodatkowo mogli wybrać rodzaj analizy: próby zależne / niezależne.
Podejście z próbami niezależnymi (chociaż to było badanie skuteczności leku) wcale nie było takie idiotyczne, ze względu na znaczne braki w danych i długie odstępy między pomiarami, a także innymi czynnikami, których nie mogę tutaj wspominać.
Przy wyborze "próby zależne" stosowało się różne algorytmy "wypełniania" braków, np. LOCF. Oczywiście lekarze byli poinformowani i świadomi tego, co ze sobą niesie takie czy inne podejście.

Zatem - lekarz wchodził na stronę statystyk, wybierał określony ich zestaw i dostawał ogólne wyniki - ciach, i kolejne, i kolejne. Dzięki temu lekarze mieli stały pogląd na to, co się dzieje w danym programie.

Wynikiem była po prostu tabelka istotności różnic pomiędzy kolejnymi "checkpointami" programu albo tabela statystyk opisowych.


Obrazek


Obrazek


Obrazek


A tutaj - przykład kodu. Tak to może wyglądać :)
Nie wklejam tekstu, bo jest tego trochę, a poza tym silnik tego forum "obcina" formatowanie (wcięcia).

Przygotowanie kwerend SQL:

Obrazek


Pierwsza - wynik w postaci osobnych kolumn:

Obrazek


Druga - wynik w postaci variable-factor (rekordami):

Obrazek


Kod metody main:
I
Obrazek

II
Obrazek

III
Obrazek


Kod metody "steps" (kroki scenariusza :) )
I część:
Obrazek

II część:
Obrazek

III część:
Obrazek
Adrian Olszewski edytował(a) ten post dnia 20.08.08 o godzinie 13:14

Temat: Współpraca .NET i R - biblioteka dla systemów analitycznych.

Ci, którzy wybierają się na WZUR ( http://www.goldenline.pl/forum/r/395702 ), będą mogli przyjrzeć się "temu czemuś" bliżej.

Kto wie, może wspólnymi siłami coś się z tego kiedyś wykroi... :)

Następna dyskusja:

Literatura Text Mining dla ...




Wyślij zaproszenie do