Weblog Tomasza Przechlewskiego [Zdjęcie T. Przechlewskiego]


scrum
random image [Photo gallery]
Zestawienie tagów
1-wire | 18b20 | 1wire | 2140 | 3rz | adamowicz | alsamixer | amazon | anniversary | antypis | apache | api | applebaum | arm | armenia | astronomy | asus | atom.xml | awk | aws | bachotek | bakłażan | balcerowicz | balta | banan | bash | batumi | berlin | bibtex | bieszczady | biznes | blogger | blogging | blosxom | bme280 | bono | borne-sulinowo | breugel | bt747 | budapeszt | budyń | bursztyn | canon | cedewu | chello | chiller | chillerpl | chown | chujowetaśmy | ciasto | cmentarz | contour | coronavirus | covid19 | cron | css | csv | curl | cycling | d54250wykh | dbi | debian | dejavu | dhcp | dht22 | dia | docbook | dom | dp1500 | ds18b20 | dulkiewicz | dyndns | dynia | ebay | economy | ekonomia | elka | elm | emacs | emacs23 | english | ep | erasmus | erasmusplus | ess | eu | eurostat | excel | exif | exiftool | f11 | fc | fc11 | fc15 | fc29 | fc5 | fc8 | fedora | fedora21 | fenix | ffmpeg | finepix | firefox | flickr | folau | fontforge | fontspec | fonty | food | fop | foto | france | francja | fripp | froggit | fuczki | fuji | fuse | gammu | garmin | gawk | gazwyb | gdańsk | gdynia | gender | geo | geocoding | georgia | gft | git | github | gmail | gmaps | gnokii | gnus | google | googlecl | googleearth | googlemaps | gotowanie | gphoto | gphoto2 | gps | gpsbabel | gpsphoto | gpx | gpx-viewer | greasemonkey | gruzja | grzyby | haldaemon | handbrake | hhi | historia | history | hitler | holocaust | holokaust | hp1000se | hpmini | humour | iblue747 | ical | iiyama | ikea | imap | inkscape | inne | internet | j10i2 | javascript | jhead | k800i | kajak | kamera | karob | kleinertest | kml | kmobiletools | knuth | kociewie kołem | kod | kolibki | komorowski | konwersja | krutynia | kuchnia | kurski | latex | latex2rtf | latex3 | lcd | legend | lenny | lesund | lewactwo | lgbt-folly | liberation | linksys | linux | lisp | lisrel | litwa | lizbona | logika | ltr | lubowla | lwp | lwów | m2wś | malta | mapquest | mapsource | marchew | marimekko | marvell | math | mathjax | mazury | mbank | mediolan | mencoder | mevo | mh17 | michalak | michlmayr | microsoft | monitor | mp4box | mplayer | ms | msc | mssql | msw | mswindows | mtkbabel | museum | muzyka | mymaps | mysql | nafisa | nanopi | natbib | navin | nekrolog | neo | neopi | netbook | niemcy | niemieckie zbrodnie | nikon | nmea | nowazelandia | nuc | nxml | oauth | oauth2 | obituary | odessa | okular | olympus | ooffice | ooxml | opera | osm | otf | otftotfm | other | overclocking | ozbekiston | panoramio | paryż | pdf | pdfpages | pdftex | pdftk | pedophilia | perl | photo | photography | picasa | picasaweb | pim | pine | pis | pit | plotly | pls | plugin | po | podróże | pogoda | politics | polityka | polsat | portugalia | postęp | powerpoint | połtawa | prelink | problem | propaganda | pstoedit | putin | python | pywws | r | radio | random | raspberry | raspberry pi | raspberrypi | raspbian | refugees | relaxng | ridley | router | rower | rowery | rpi | rsync | rtf | ruby | rugby | rumunia | russia | rwc | rwc2007 | rwc2011 | rwc2019 | rzym | samba | sds011 | selenium | sem | sernik | sheevaplug | sienkiewicz | signature | sks | skype | skytraq | smoleńsk | sqlite | srtm | sshfs | ssl | staszek wawrykiewicz | statistics | stats | statystyka | stix | stretch | suwałki | svg | svn | swanetia | swornegacie | szwajcaria | słowacja | tbilisi | terrorism | tex | texgyre | texlive | thunderbird | tomato | totalnaopozycja | tourism | tramp | trang | transylwania | truetype | ttf | turcja | turkey | turystyka | tusk | tv | tv5monde | twitter | typetools | ubuntu | uchodźcy | udev | ue | ukraina | umap | unix | upc | updmap | ups | utf8 | uzbekistan | varia | video | vienna | virb edit | vostro | wammu | wdc | wdfs | weather | weathercloud | webcam | webdav | webscrapping | weewx | wh2080 | wiedeń | wikicommons | wilno | win10 | windows | windows8 | wine | wioślarstwo | word | wordpress | wrt54gl | ws1080 | wtyczka | wunderground | ww2 | www | wybory | wybory2015 | włochy | węgry | xemex | xetex | xft | xhtml | xine | xml | xmllint | xsd | xslt | xvidtune | youtube | yum | zakopane | zakupy | zdf | zdrowie | łeba | świdnica | żywność
Archiwum
O stronie
wykorzystywany jest blosxom plus następujące wtyczki: tagging, flatarchives, rss10, lastbuilddatexhtmlmime. Niektóre musiałem dopasować nieco do swoich potrzeb. Więcej o blosxom jest tutaj
Subskrypcja
RSS 1.0
Master-plan Jacka Sasina

Przyznam się że typa nie lubię. Oceniam go jako nietypowego partyjnego aparatczyka: mierny ale wierny, tyle że nie bierny (w tym sensie nietypowy, co w połączeniu z cechą pierwszą powoduje, że nawet gorszy niż ten co niewiele robi). Sasin działa. Jest gwiazdą TV (nie oglądam wywiadów z tą gwiazdą). Jest także autorem dwóch projektów, które zapamiętałem: 1) zmiana granic okręgów wyborczych w wyborach samorządowych celem ułatwienia wyboru kandydata PiS (Ustawa o ustroju miasta stołecznego Warszawy; więcej google: zmiana+granic+okręgów+Sasin) oraz 2) pozbawienie prezydent Łodzi Hanny Zdanowskiej biernego prawa wyborczego (Sasin o Zdanowskiej: Nawet jeśli wygra, nie będzie rządzić; więcej: google: zdanowska+sasin)

Wszystkie te projekty mają jeden wspólny mianownik: 1) dotyczyły wyborów, 2) były na wariata, 3) nie wyszły. OK, wybory 10-05-2020 mogą wyjść, bo się jeszcze nie odbyły. Jest teoretycznie szansa, że panu premierowi odwróci się karta, ale ja powiem już dziś: myślę, że wątpię. Powiem więcej: ten project jest tak na wariata, że cały czas mam przeświadczenie, że to dywersja (zwana także zasłoną dymną). Tj. prawdziwy projekt jeszcze nie został ujawniony.

Przy czym projekt wybory korespondencyjne sam w sobie nie jest zły. Nie jest ani niebezpieczny dla zdrowia (bzdura wymyślona przez opozycję) ani nie jest niekonstytucyjny (kolejna bzdura). W stanie Oregon od 1998 roku wybory są wyłącznie korespondencyjne, tyle że w Oregonie: pakiety są wysyłane trzy tygodnie przed dniem głosowania, a w zasadzie liczenia głosów (co daje możliwość reklamowania się jak się koperty nie dostało), podpisane koperty zwrotne są weryfikowane z podpisem wyborcy z rejestru (coś jak weryfikacja podpisu w banku, co mocno IMO ogranicza możliwość wysyłania głosów za kogoś), komisja potwierdza przyjęcie ważnego głosu (SMSem). Wszystkie wymienione pozwalają moim zdaniem ograniczyć możliwe fałszerstwa i omyłki. Powiem że a la Oregon to ja bym nawet wolał niż łazić do lokalu i głosować osobiście (i pewnie by taniej wyszło). No ale to co wymyślił Sasin to się ma jak pięść do nosa do procedury oregońskiej: jaka jest gwarancja formalna że każdy dostanie kartę do głosowania, jak list ma być dostarczony 3 dni przed i nierejestrowany? Jak wykryć fałszerstwa? Wolne żarty, że się będzie zatrudniać grafologa. Załóżmy, że wpłynie 50 tys skarg na fałszywy podpis pod kartą złożonych nawet złośliwie przez opozycyjnych członków komisji (mają prawo nawet do obstrukcji, podobnie jak PiS co nie miał żadnych podstaw ale składał protesty w ostatnich wyborach samorządowych, bo ,,różnica była mała''). No więc kiedy wtedy SN by uznał ważność wyborów? Za 10 lat? Albo hurtem oddalił wszystkie protesty?

Tak to widzę...

url | Sun, 26/04/2020 06:14 | tagi: ,
Worldometer vs ECDC

Jak już pisałem danych nt COVID19 jest multum bo są traktowane jako treść promocyjna, przyciągająca klikających. Każda tuba medialna (gazeta/portal/telewizja) w szczególności publikuje dane nt.

Źródłem pierwotnym każdego wydają się być raporty narodowe (bo jak inaczej), ale ponieważ te raporty narodowe są składane w różny sposób, to ich połączenie w jedną bazę też różnie może wyglądać. Generalnie ci co takie bazy robią to albo przyznają się, że działają na hmmm niekonwencjonalnych źródłach (Twitter) albo nic nie piszą, skąd mają dane. Mają i już...

Wydaje się (chyba, że czegoś nie wiem), że ECDC, OWiD, CSSE oraz Worldometers (dalej WMs) są najpopularniejszymi źródłami danych nt COVID19 w przekroju międzynarodowym. (Nawiasem mówiąc: WHO nie publikuje danych -- publikuje raporty z danymi w formacie PDF. Wydobycie z nich danych jest nietrywialne i kosztowne, bo nie da się tego na 100% zautomatyzować. W rezultacie prawie nikt nie powołuje się na WHO jako źródło danych -- lekki szejm przyznajmy, bo niby ta organizacja jest od tego żeby m.in. zbierać i udostępniać informację n/t.) Taka drobna różnica na początek: ECDC, OWiD oraz CSSE to prawdziwe bazy: zarejestrowane z dzienną częstotliwością zgony, przypadki, testy i co tam jeszcze. OWiD kopiuje dane z ECDC, kiedyś kopiowało z WHO ale napisali że WHO zawierało liczne błędy i to ich skłoniło do korzystania z ECDC (0:2 dla WHO). WMs publikuje stan na, bazy jako takiej nie ma (przynajmniej publicznie albo nie potrafię jej odszukać na stronie). Można założyć że jak się ogląda stronę WMs z ,,notowaniami'' nt/ koronawirusa w dniu X o godzinie T to jest to stan na X:T. Nawiasem mówiąc tak jest wygodniej, ale jednocześnie komplikuje to sprawę w aspekcie: dzienna liczba przypadków chociażby z uwagi na różnice czasu (jak w PL kończy się dzień to na Fiji jest w połowie inny; inna sprawa, że wątpię żeby ktoś się tym przejmował). Niemniej WMs ma rubrykę "nowe przypadki", tyle że nie bardzo wiadomo co to znaczy...

No więc po tym przydługim wstępie do rzeczy: jak się mają dane z WMs względem ECDC? Jak wspomniałem, na stronie WMs nie ma bazy -- jest tabela z danymi ze stanem ,,na teraz''. ECDC z kolei publikuje bazę w postaci arkusza kalkulacyjnego. Ściągam dane codziennie. Ze strony WMs o 21:00 (koniec dnia, przynajmniej w PL) oraz o 23:00 ze strony ECDC. Dane te wyglądają jakoś tak (WMs, po konwersji HTML→CSV):

date;country;totalC;newC;totalD;newD;totalT
04040600;USA;277467;+306;7402;+10;830095

Stempel czasu jest ustalany w momencie pobrania danych. Na stronie WMs czas nie jest podany explicite (nie ma czegoś takiego jak np. dane aktualizowano o H:M). Czyli 04040600 to dane z 2020/04/04 z godziny 6:00.

Dane ECDC wyglądają jakoś tak:

date;id;country;newc;newd;totalc;totald
2020-04-04;US;United_States_of_America;32425;1104;277965;7157

NewC -- nowe przypadki (dzienne); NewD -- nowe zgodny; totalC -- przypadki łącznie; totalD -- zgony łącznie. Baza ECDC ma stempel czasu (dzień).

W przypadku PL wiem, że Ministerstwo Zdrowia (MinZ) publikuje dane generalnie o godzinie 10-coś-tam oraz o 17/18-coś-tam. (Czemu tak nie wiem). Patrząc na dane z WMs wiedzę, że o 21:00 publikują już dane aktualne na ten dzień, w tym sensie, że uwzględnią stan z ostatniego dziennego komunikatu MinZ (ale jakiego formalnie dnia te dane dotyczą, to już inna sprawa, bo ten dzień przecież się nie skończył :-)). Jeżeli chodzi o ECDC to dane pobrane w dniu X zawierają dane do dnia X-1, żeby było śmieszniej ECDC dla tego dnia przypisuje dane z komunikatu MinZ z dnia X-2. Czyli na przykładzie: arkusz pobrany o 23:00 dnia 24/04/2020 będzie miał ostatni wiersz datowany 23/04 ale dane w tym wierszu będą tymi które pojawiły się na stronie MinZ w dniu 22/04.

Uzbrojony o tę wiedzę dla wybranych 24 krajów wykreśliłem dane (z kwietnia) w wersji WMs oraz ECDC, w dwóch wariantach: z oryginalnymi stemplami czasowymi (górny wiersz) oraz ze stemplem skorygowanym przy założeniu że dane ECDC są 24H opóźnione (czyli dzień 23/04 tak naprawdę to dzień 22/04 itd). Te ,,skorygowane dane'' to dolny wiersz. Dla 90% krajów dane łącznie nakładają się czyli dane są identyczne (są wyjątki--ciekawe czemu). Dane dzienne to misz-masz, każda baza ma własną wersję, nie wiadomo która jest prawdziwa, tyle, że ECDC ma zawsze dane dzienne a WMs niekoniecznie (dla Japonii prawie zawsze ta kolumna była pusta)

Dane i komplet wykresów jest tutaj

Poniżej kilka wybranych krajów:





url | Sun, 26/04/2020 05:17 | tagi: , ,
Wykresy typu Marimekko na przykładzie COVID19

Marimekko to zestawiony do 100% wykres słupkowy, gdzie szerokość słupka jest proporcjonalna do jego udziału w liczebności. (https://predictivesolutions.pl/wykres-marimekko-czyli-analityczny-patchwork)

Nie wiem o co chodzi, ale patrząc na przykłady, to jest to wykres pokazujący strukturę dwóch zmiennych na raz. Coś jak skumulowany wykres słupkowy (stacked barchart), tyle że słupki mają zmienną szerokość, odpowiadającą udziałom/liczebnościom wartości jednej cechy. Dla każdego słupka z kolei poszczególne segmenty mają wysokości proporcjonalne do udziałów/liczebności wartości drugiej cechy (w tym słupku). Alternatywną nazwą jest wykres mozaikowy.

Ale jest też trochę inny wariant takich wykresów, dla przypadku kiedy dla każdej jednostki w populacji generalnej jest Wi = Ci/Ni. Jeżeli wysokość słupka jest proporcjonalna do wartości Wi, szerokość jest proporcjonalna do Ni, to pola są oczywiście w proporcji Ci. Przykładowo jeżeli populacją generalną są kraje świata, wartością cechy Ni jest liczba mieszkańców w kraju i, wartością cechy Ci wielkość emisja CO2 w kraju i, to Wi jest oczywiście emisją per capita.

Moim zdaniem użyteczne, bo pokazuje na raz dwa natężenia: łączne, w skali całej populacji oraz szczegółowe, w skali jednostki. Kontynuując przykład: ile emituje przeciętny mieszkaniec kraju i oraz jaki jest udział emisji kraju i w całości emisji.

W przypadku epidemii COVID19 podstawową zmienną jest liczba zarażonych/zmarłych w kraju i. Ale jeżeli chcemy porównać kraj i z krajem j to oczywiście należy uwzględnić liczbę mieszkańców w obu krajach. Czyli wysokości słupków powinny odpowiadać liczbie zarażonych/zmarłych na jednostkę (np. na 1mln) a szerokości liczbie mieszkańców:

library(ggplot2)
library(dplyr)

dat <- "2020/04/09"

d <- read.csv("indcs.csv", sep = ';',  header=T, na.string="NA");
## liczba ludności w milionach (szerokość):
d$popm <- d$pop / million

## Oblicz współczynniki na 1mln
d$casesr <- d$cases/d$popm
### Wysokość:
d$deathsr <- d$deaths/d$popm

## Ograniczamy liczbę krajów żeby zwiększyć czytelność wykresu
## Tylko kraje wykazujące zmarłych
d <- d %>% filter(deaths > 0) %>% as.data.frame
## Tylko kraje z min 2/1mln i populacji > 1mln
d9 <- d %>% filter(deathsr > 2 & popm > 3 & deaths > 49) %>% droplevels() %>%
 arrange (deathsr) %>% as.data.frame

d9$w <- cumsum(d9$popm)
d9$wm <- d9$w - d9$popm
d9$wt <- with(d9, wm + (w - wm)/2)

d8$w <- cumsum(d8$popm)
d8$wm <- d8$w - d8$popm
d8$wt <- with(d8, wm + (w - wm)/2)

## Dzielimy etykiety na dwie grupy
## (inaczej wiele etykiet zachodzi na siebie)
d9$iso3h <- d9$iso3
d9$iso3l <- d9$iso3
## Kraje o niskich  wartościach bez etykiet
d9$iso3h[ (d9$popm < 15 ) ] <- ""
## Kraje o wysokich  wartościach bez etykiet
d9$iso3l[ (d9$popm >= 15 ) ] <- ""

p9  <- ggplot(d9, aes(ymin = 0)) +
  ylab(label="mratio (deaths/1mln)") +
  xlab(label="population (mln)") +
  ggtitle(sprintf("COVID19 mortality (%s | mratio > 2 | population > 3mln )", dat), 
      subtitle="source: https://www.ecdc.europa.eu/en/covid-19-pandemic (twitter.com/tprzechlewski)") +
  geom_rect(aes(xmin = wm, xmax = w, ymax = deathsr, fill = iso3)) +
  geom_text(aes(x = wt, y = 0, label = iso3h), vjust=+0.5, hjust=+1.25, size=2.0, angle = 90) +
  geom_text(aes(x = wt, y = 0, label = iso3l), vjust=+0.5, hjust=-0.20, size=1.5, angle = 90) +
  theme(legend.position = "none") 
  ## ... podobnie dla zmiennej casesr

Wynik w postaci rysunków:



Powyższe jest dostępne tutaj

url | Mon, 13/04/2020 19:27 | tagi: , , ,
Więcej wykresów nt COVID19

Wymyśliłem sobie wykreślić wykresy pokazujące zależność pomiędzy liczbą zarażonych/zmarłych, a wybranymi wskaźnikami: GDP (zamożność), oczekiwana długość życia (poziom służby zdrowia) oraz śmiertelność dzieci (zamożność/poziom rozwoju). Większość danych pobrałem z portalu OWiD:

Dane dotyczące liczby ludności są z bazy Banku Światowego (https://data.worldbank.org/indicator/sp.pop.totl.) Dane dotyczące zarażonych/zmarłych ze strony ECDC (www.ecdc.europa.eu/en/covid-19/data-collection) Scaliłem wszystko do kupy skryptem Perlowym. NB pojawił się tzw. small problem, bo bazy OWiD oraz WorldBank używają ISO-kodów 3-literowych krajów, a ECDC dwuliterowych (PL vs POL). Trzeba było znaleźć wspólny mianownik. Szczęśliwie Perl ma gotowy moduł. Oprócz tego ECDC stosuje EU-standard w przypadku Grecji (EL zamiast GR) oraz Wielkiej Brytanii (UK/GB).

#!/usr/bin/perl
use Locale::Codes::Country;
...
while (<COVID>) { chomp();
($date, $iso2, $country, $newc, $newd, $totalc, $totald) = split /;/, $_;

   $iso3 = uc ( country_code2code($iso2, 'alpha-2', 'alpha-3'));
}

Rezultat jest zapisywany do pliku o następującej zawartości:

iso3;country;lex2019;gdp2016;cm2017;pop2018;cases;deaths
ABW;Aruba;76.29;NA;NA;105845;77;0
AFG;Afghanistan;64.83;1929;6.79;37172386;423;14
...

Wierszy jest 204, przy czym niektórym krajom brakuje wartości. Ponieważ dotyczy to krajów egzotycznych, zwykle małych, to pominę je (nie teraz później, na etapie przetwarzania R-em). Takich wybrakowanych krajów jest 49 (można grep-em sprawdzić). Jedynym większym w tej grupie jest Syria, ale ona odpada z innych powodów.

Do wizualizacji wykorzystam wykres punktowy (dot-plot) oraz wykresy rozrzutu (dot-plot).

library("dplyr")
library("ggplot2")
library("ggpubr")
## 
options(scipen=1000000)
## https://www.r-bloggers.com/the-notin-operator/
`%notin%` <- Negate(`%in%`)
##
today <- Sys.Date()
tt<- format(today, "%d/%m/%Y")
million <- 1000000
## Lista krajów Europejskich + Izrael
## (pomijamy kraje-liliputy)
ee <- c(
'BEL', 'GRC', 'LTU', 'PRT', 'BGR', 'ESP', 'LUX', 'ROU', 'CZE', 'FRA', 'HUN',
'SVN', 'DNK', 'HRV', 'MLT', 'SVK', 'DEU', 'ITA', 'NLD', 'FIN', 'EST', 'CYP',
'AUT', 'SWE', 'IRL', 'LVA', 'POL', 'ISL', 'NOR', 'LIE', 'CHE', 'MNE', 'MKD',
'ALB', 'SRB', 'TUR', 'BIH', 'BLR', 'MDA', 'UKR', 'ISR', 'RUS', 'GBR' );
ee.ee <- c('POL')

d <- read.csv("indcs.csv", sep = ';',  header=T, na.string="NA");
## Liczba krajów
N1 <- nrow(d)
## liczba ludności w milionach
d$popm <- d$pop / million

## Oblicz współczynniki na 1mln 
d$casesr <- d$cases/d$popm 
d$deathsr <- d$deaths/d$popm 

## Tylko kraje wykazujące zmarłych
d <- d %>% filter(deaths > 0) %>% as.data.frame
## Liczba krajów wykazujących zmarłych
N1d <- nrow(d)

## Tylko kraje z kompletem wskaźników (pomijamy te z brakami)
d <- d[complete.cases(d), ]

nrow(d)

##  UWAGA: pomijamy kraje o wsp. <= 2
##  droplevels() usuwa `nieużywane' czynniki
##  mutate zmienia kolejność na kolejność wg dearhsr:
d9 <- d %>% filter(deathsr > 2 ) %>% droplevels() %>% 
 mutate (iso3 = reorder(iso3, deathsr)) %>% as.data.frame

N1d2 <- nrow(d9)
M1d2 <- median(d9$deathsr, na.rm=T)

## https://stackoverflow.com/questions/11093248/geom-vline-with-character-xintercept
## Wykres punktowy
rys99 <- ggplot(d9, aes(x =iso3, y = deathsr )) +
  geom_point(size=1, colour = 'steelblue', alpha=.5) +
  xlab(label="Country") +
  ylab(label="Deaths/1mln") +
  ggtitle(sprintf("COVID19 mortality in deaths/mln (as of %s)", tt), 
   subtitle=sprintf("Countries with ratio > 0: %i | Countries with ratio > 2.0: N=%i (median %.1f)", 
       N1d, N1d2, M1d2)) +
  theme(axis.text = element_text(size = 4)) +
  ##theme(plot.title = element_text(hjust = 0.5)) +
  scale_y_continuous(breaks=c(0,20,40,60,80,100,120,140,160,180,200,220,240,260,280,300,320,340,360)) +
  geom_hline(yintercept=M1d2, linetype="solid", color = "steelblue") +
  geom_vline(aes(xintercept = which(levels(iso3) == 'POL')), size=1, color="#8A0303", alpha=.25) +
  geom_vline(aes(xintercept = which(levels(iso3) == 'DEU')), size=1, color="#8A0303", alpha=.25) +
  geom_vline(aes(xintercept = which(levels(iso3) == 'SWE')), size=1, color="#8A0303", alpha=.25) +
  coord_flip()

Uwaga: oś OX to skala porządkowa. Czynniki powinny być uporządkowane wg. wartości zmiennej z osi OY, czyli według deathsr. Do tego służy funkcja mutate (iso3 = reorder(iso3, deathsr). Można też uporządkować je ,,w locie'' aes(x =iso3, y = deathsr ), ale wtedy niepoprawnie będą kreślone (za pomocą geom_vline) linie pionowe. Linie pionowe służą do wyróżnienia pewnych krajów. Linia pozioma to linia mediany.

sources <- sprintf ("As of %s\n(Sources: %s %s)", tt,
  "https://www.ecdc.europa.eu/en/covid-19-pandemic",
  "https://ourworldindata.org/")

## Żeby etykiety nie zachodziły na siebie tylko dla wybranych krajów
## Add empty factor level! Istotne inaczej będzie błąd
# https://rpubs.com/Mentors_Ubiqum/Add_Levels
d$iso3 <- factor(d$iso3, levels = c(levels(d$iso3), ""))

d$iso3xgdp <- d$iso3
d$iso3xlex <- d$iso3
d$iso3xcm <- d$iso3

## Kraje o niskich  wartościach bez etykiet
## Bez etykiet jeżeli GDP<=45 tys oraz wskaźnik < 50:
d$iso3xgdp[ (d$gdp2016 < 45000) & (d$deathsr < 50 ) ] <- ""
## Inne podobnie
d$iso3xlex[ ( (d$lex2019 < 80) | (d$deathsr < 50 ) ) ] <- ""
d$iso3xcm[ ((d$cm2017 > 1.2) | (d$deathsr < 50 ) ) ] <- ""

## GDP vs współczynnik zgonów/1mln
rys1 <- ggplot(d, aes(x=gdp2016, y=deathsr)) + 
  geom_point() +
  geom_text(data=d, aes(label=sprintf("%s", iso3xgdp), x=gdp2016, y= deathsr), vjust=-0.9, size=2 ) +
  xlab("GDP (USD, Constant prices)") + 
  ylab("deaths/1mln") + 
  geom_smooth(method="loess", se=F, size=2) +
  ggtitle("GDP2016CP vs COVID19 mortality", subtitle=sources)

## Life ex vs współczynnik zgonów/1mln
rys2 <- ggplot(d, aes(x=lex2019, y=deathsr)) + 
  geom_point() +
  geom_text(data=d, aes(label=sprintf("%s", iso3xlex), x=lex2019, y= deathsr), vjust=-0.9, size=2 ) +
  xlab("Life expentancy") + 
  ylab("deaths/1mln") + 
  geom_smooth(method="loess", se=F, size=2) +
  ggtitle("Life expentancy vs COVID19 mortality", subtitle=sources)

## Child mortality vs współczynnik zgonów/1mln
rys3 <- ggplot(d, aes(x=cm2017, y=deathsr)) + 
  geom_point() +
  geom_text(data=d, aes(label=sprintf("%s", iso3xcm), x=cm2017, y= deathsr), vjust=-0.9, size=2 ) +
  xlab("Child mortality %") +
  ylab("deaths/1mln") + 
  geom_smooth(method="loess", se=F, size=2) +
  ggtitle("Child mortality vs COVID19 mortality", subtitle=sources)

## GDP vs Child mortality 
rys0 <- ggplot(d, aes(x=gdp2016, y=cm2017)) + 
  geom_point() +
  xlab("GDP (USD, Constant prices)") + 
  ylab("Child mortality") +
  geom_smooth(method="loess", se=F, size=2) +
  ggtitle("GDP2016CP vs Child mortality", subtitle=sources)

Jeszcze raz dla krajów Europejskich:

## Tylko kraje Europejskie:
d <- d %>% filter (iso3 %in% ee) %>% as.data.frame

d$iso3xgdp <- d$gdp2016
d$iso3xlex <- d$lex2019
d$iso3xcm <- d$cm2017
d$iso3xgdp[ d$iso3 %notin% ee.ee ] <- NA
d$iso3xlex[ d$iso3 %notin% ee.ee ] <- NA
d$iso3xcm[ d$iso3 %notin% ee.ee ] <- NA

rys1ec <- ggplot(d, aes(x=gdp2016, y=casesr)) + 
  geom_point() +
  geom_text(data=d, aes(label=sprintf("%s", iso3), x=gdp2016, y= casesr), vjust=-0.9, size=2 ) +
  geom_point(data=d, aes(x=iso3xgdp, y= casesr), size=2, color="red" ) +
  xlab("GDP (USD, Constant prices") + 
  ylab("cases/1mln") +
  geom_smooth(method="loess", se=F, size=2) +
  ggtitle("GDP2016CP vs COVID19 cases (Europe)", subtitle=sources)
  ... itd...

Wynik w postaci rysunków:




Powyższe jest dostępne tutaj

url | Mon, 13/04/2020 05:12 | tagi: , ,
Źródła danych nt #Covid19 podsumowanie (wersja 04/2020)

Danych nt COVID19 jest multum bo są traktowane jako treść promocyjna, przyciągająca klikających. Każda tuba medialna (gazeta/portal/telewizja) w szczególności publikuje dane nt

Niestety z faktu, że danych nt COVID19 jest multum niewiele wynika, bo wszystkie są do dupy, w sensie że są wątpliwej jakości, tj. zwykle sposób w jaki są gromadzone nie jest opisany. Nie wiadomo kto jest klasyfikowany jako zarażony COVID19, nie wiadomo kto jest klasyfikowany jako zmarły w wyniku zarażenia COVID19. Można się domyślać że klasyfikowany jako zarażony COVID19 jest ten komu wykonany słynny test (w większości wypadków, podobno nie zawsze); zmarły w wyniku zarażenia COVID19 jest ten, któremu lekarz wypisał świadectwo zgonu ze stosownym wpisem.

Powyższe skutkuje: niemożnością oceny prawdziwej skali zjawiska (stąd teorie że rząd fałszuje) oraz niemożnością dokonania wiarygodnych porównań międzynarodowych.

Jeżeli chodzi o Polskę, to nikt nie prowadzi publicznego rejestru. Strona GIS to w ogóle kuriozalnie wygląda. Są komunikaty, jak ktoś ma czas to może jest sobie z nich dane wydłubywać i agregować. Na poziomie międzynarodowym są 2 źródła agregacji pierwotnej nazwijmy to: WHO oraz ECDC. Te dwa źródła agregują dane nadsyłane przez ciała krajowe, wg jakiejś niezdefiniowanej (przypuszczalnie ad hoc ustalanej) procedury. Inni korzystają z danych WHO/ECDC pośrednio lub bezpośrednio ewentualnie uzupełniając/modyfikując je w bliżej niezdefiniowany sposób. No i są jeszcze źródła specyficzne takie jak Google Community Mobility Reports.

WHO Situation Reports. To nie jest baza danych, ale pliki PDF zawierające raporty w tym dane. Pozyskanie z nich danych wymaga nietrywialnej konwersji. www.who.int/emergencies/diseases/novel-coronavirus-2019/situation-reports . Dane z raportów dostępne są m.in. na stronie Wikipedii: en.wikipedia.org/wiki/2019%E2%80%9320_coronavirus_pandemic_cases/WHO_situation_reports oraz en.wikipedia.org/wiki/Talk:2019%E2%80%9320_coronavirus_pandemic_cases/WHO_situation_reports

ECDC.europa.eu Dane udostępniane w postacji codziennie aktualizowanego arkusza kalkulacyjnego. www.ecdc.europa.eu/en/covid-19/data-collection [Since the beginning of the coronavirus pandemic, ECDC's Epidemic Intelligence team has been collecting the number of COVID-19 cases and deaths, based on reports from health authorities worldwide.]

John Hopkins Univ/CSSE github.com/CSSEGISandData/COVID-19 [To identify new cases, we monitor various twitter feeds, online news services, and direct communication sent through the dashboard. Before manually updating the dashboard, we confirm the case numbers using regional and local health departments, namely the China CDC (CCDC), Hong Kong Department of Health, Macau Government, Taiwan CDC, European CDC (ECDC), the World Health Organization (WHO), as well as city and state level health authorities.]

Worldometers https://worldometers.info/coronavirus/ [nie wiadomo jak zbierane, przypuszczalnie kopiowane z WHO/ECDC; Worldometers, to -- wydaje się -- inicjatywa PR-owa firmy produkującej oprogramowanie]

OWiD czyli Our World in Data wykorzystuje bazę ECDC. ourworldindata.org/coronavirus-source-data [na podstawie ECDC]

Reasumując: jak ktoś potrzebuje gotowego zbioru danych, to ma do wyboru ECDC/OWiD/CSSE. Wszystkie są wątpliwe, ale lepszych nie ma a ci przynajmniej podają (ogólnikowo to fakt) jak te dane zbierają. Jak ktoś używa worldometers to pytanie czemu to robi... Jak posługuje się jeszcze innymi bardziej egoztycznymi danymi to szkoda tracić czasu na jego analizy (ew. sprawdzić czy nie są to dane ECDC/OWiD/CSSE tylko pod inną marką sprzedawane).

W Polsce nie ma oficjalnego rejestru. Przynajmniej ja nic nie wiem na temat. To tak nawiasem mówiąc szejm. Że żaden urząd, uniwersytet czy instytut nie udostępnia oficjalnych/wiarygodnych/kompletnych/łatwo dostępnych danych (w Niemczech na przykład robi to słynny RKI; a we Francji nie mniej słynny pasteur.fr). W PL zaś każdy się stara i coś tam udostępnia, z naciskiem na coś... Znalazłem rejestr nieopisany (w sensie jak/skąd są nim gromadzone dane) prowadzony przez dziennik z grupy PolskaPress. dziennikzachodni.carto.com/tables/zachorowania_na_koronawirusa_w_polsce_marzec/public

Google Community Mobility Reports To nie jest baza danych, ale zbiór raportów w formacie PDF. www.google.com/covid19/mobility/. [Google has launched a new website that uses anonymous location data collected from users of Google products and services to show the level of social distancing taking place in various locations. The COVID-19 Community Mobility Reports web site will show population data trends of six categories: Retail and recreation, grocery and pharmacy, parks, transit stations, workplaces, and residential. The data will track changes over the course of several weeks, and as recent as 48-to-72 hours prior, and will initially cover 131 countries as well as individual counties within certain states.] Ciekawostka raczej, bo w szczególności, nie do końca wiadomo co te procenty Gógla oznaczają, np. -60% względem baseline. Anie nie wiadomo co to jest ten baseline (średnia?) ani jak liczony jest ruch...

Nie mniej wydłubałem te procenty z raportów dla krajów OECD i zamieniłem na plik w formacie CSV. Jest on do pobrania tutaj.

Dane dotyczące USA. Oczywiście są częścią WHO/ECDC/CSSE. Ale są także bardziej szczegółowe:

CDC [The provisional counts for coronavirus disease (COVID-19) deaths are based on a current flow of mortality data in the National Vital Statistics System.] https://www.cdc.gov/nchs/nvss/vsrr/COVID19/index.htm

NewYork Times [The data is the product of dozens of journalists working across several time zones to monitor news conferences, analyze data releases and seek clarification from public officials on how they categorize cases.] https://github.com/nytimes/covid-19-data oraz https://www.nytimes.com/interactive/2020/us/coronavirus-us-cases.html

No i jeszcze są pewnie jakieś chińskie dane, ale to trzeba znać chiński.

url | Sat, 04/04/2020 04:40 | tagi: , ,
Korespondencyjne wybory w Bawarii


Przez przypadek ciekawe odkrycie. W niedzielę zakończyły się wybory w Bawarii, wyłącznie w trybie korespondencyjnym z uwagi na epidemię #COVID19. Jednocześnie w PL trwa wałkowanie tematu pn przesunąć wybory prezydenckie. Niewątpliwie przykład niemiecki to kłopot, że tak powiem narracyjny, dla tych co chcą przesunięcia.

No więc naiwnie wpisałem w google: bavaria+second+round+elections+postal a w rezultacie dostałem głównie strony o apelu kandydatki Kidawy o przesunięcie wyborów w tym kuriozalna relacja Reutersa -- kiedyś szanowanej agencja informacyjnej, teraz kandyjskiej dezinformacyjnej prop-tuby. W dziale "Zdrowie" -- a jakże -- donosi ona o apelu o bojkot p. Kidawy kończąc ten "zdrowotny raport" raportem pana J. Flisa z Krakowa (tak to ten sam, udający naukowca, telewizyjny-profesor Flis), ale na temat wyborów w Bawarii, które skutkowały wg. p. Flisa 2 tys ofiar (metody wyliczeń, którą posłużył się "profesor" nie podano). Zaistne niezwykle relewantny dokument do mojego zapytania.

url | Thu, 02/04/2020 04:46 | tagi: , , ,
Dane Eurostatu nt zgonów/urodzeń

Trzeba coś robić w czasie kwarantanny

## https://b-rodrigues.github.io/modern_R/
## https://gist.github.com/imartinezl/2dc230f33604d5fb729fa139535cd0b3
library("eurostat")
library("dplyr")
library("ggplot2")
library("ggpubr")
## 
options(scipen=1000000)
dformat <- "%Y-%m-%d"

eu28 <- c("AT", "BE", "BG", "HR", "CY", "CZ", "DK",
   "EE", "FI", "FR", "DE", "EL", "HU", "IE", 
   "IT", "LT", "LU", "LV", "MT", "NL", "PL", 
   "PT", "RO", "SK", "SI", "ES", "SE")
eu6 <- c("DE", "FR", "IT", "ES", "PL")

### Demo_mor/ Mortality monthly ### ### ###
dm <- get_eurostat(id="demo_mmonth", time_format = "num");
dm$date <- sprintf ("%s-%s-01", dm$time, substr(dm$month, 2, 3))
str(dm)

## There are 12 moths + TOTAL + UNKN
dm_month <- levels(dm$month)
dm_month

## Only new data
dm28  <- dm %>% filter (geo %in% eu28 & as.Date(date) > "1999-12-31")
str(dm28)
levels(dm28$geo) 

## Limit to DE/FR/IT/ES/PL:
dm6  <- dm28 %>% filter (geo %in% eu6)
str(dm6)
levels(dm6$geo) 

pd1 <- ggplot(dm6, aes(x= as.Date(date, format="%Y-%m-%d"), y=values)) + 
 geom_line(aes(group = geo, color = geo), size=.4) +
 xlab(label="") +
 ##scale_x_date(date_breaks = "3 months", date_labels = "%y%m") +
 scale_x_date(date_breaks = "6 months",
   date_labels = "%m\n%y", position="bottom") +
 theme(plot.subtitle=element_text(size=8, hjust=0, color="black")) +
 ggtitle("Deaths", subtitle="https://ec.europa.eu/eurostat/data/database (demo_mmonth)")

## Newer data
dm6  <- dm6 %>% filter (as.Date(date) > "2009-12-31")

pd2 <- ggplot(dm6, aes(x= as.Date(date, format="%Y-%m-%d"), y=values)) + 
 geom_line(aes(group = geo, color = geo), size=.4) +
 xlab(label="") +
 scale_x_date(date_breaks = "3 months", date_labels = "%m\n%y", position="bottom") +
 theme(plot.subtitle=element_text(size=8, hjust=0, color="black")) +
 ggtitle("Deaths", subtitle="https://ec.europa.eu/eurostat/data/database (demo_mmonth)")

ggsave(plot=pd1, file="mort_eu_L.png", width=12)
ggsave(plot=pd2, file="mort_eu_S.png", width=12)
## Live births (demo_fmonth) ### ### ###

dm <- get_eurostat(id="demo_fmonth", time_format = "num");
dm$date <- sprintf ("%s-%s-01", dm$time, substr(dm$month, 2, 3))
str(dm)

## There are 12 moths + TOTAL + UNKN
dm_month <- levels(dm$month)
dm_month

dm28  <- dm %>% filter (geo %in% eu28 & as.Date(date) > "1999-12-31")
str(dm28)
levels(dm28$geo) 

dm6  <- dm28 %>% filter (geo %in% eu6)
str(dm6)
levels(dm6$geo) 

pd1 <- ggplot(dm6, aes(x= as.Date(date, format="%Y-%m-%d"), y=values)) + 
 geom_line(aes(group = geo, color = geo), size=.4) +
 xlab(label="") +
 ##scale_x_date(date_breaks = "3 months", date_labels = "%y%m") +
 scale_x_date(date_breaks = "6 months", date_labels = "%m\n%y", position="bottom") +
 theme(plot.subtitle=element_text(size=8, hjust=0, color="black")) +
 ggtitle("Births", subtitle="https://ec.europa.eu/eurostat/data/database (demo_fmonth)")

##
dm6  <- dm6 %>% filter (as.Date(date) > "2009-12-31")

pd2 <- ggplot(dm6, aes(x= as.Date(date, format="%Y-%m-%d"), y=values)) + 
 geom_line(aes(group = geo, color = geo), size=.4) +
 xlab(label="") +
 scale_x_date(date_breaks = "3 months", date_labels = "%m\n%y", position="bottom") +
 theme(plot.subtitle=element_text(size=8, hjust=0, color="black")) +
 ggtitle("Births", subtitle="https://ec.europa.eu/eurostat/data/database (demo_fmonth)")

ggsave(plot=pd1, file="birt_eu_L.png", width=12)
ggsave(plot=pd2, file="birt_eu_S.png", width=12)
## Population (only) yearly ### ### ##
## Population change - Demographic balance and crude rates at national level (demo_gind)
dp <- get_eurostat(id="demo_gind", time_format = "num");
dp$date <- sprintf ("%s-01-01", dp$time)
str(dp)
dp_indic_dic <-  get_eurostat_dic("indic_de")

dp_indic_dic
dp28  <- dp %>% filter (geo %in% eu28 & time > 1999 & indic_de == "JAN")

str(dp28)
dp6  <- dp28 %>% filter (geo %in% eu6)

pdp1 <- ggplot(dp6, aes(x= as.Date(date, format="%Y-%m-%d"), y=values)) + 
        geom_line(aes(group = geo, color = geo), size=.4) +
        xlab(label="") +
        ##scale_x_date(date_breaks = "3 months", date_labels = "%y%m") +
        ##scale_x_date(date_breaks = "6 months", date_labels = "%m\n%y", position="bottom") +
        theme(plot.subtitle=element_text(size=8, hjust=0, color="black")) +
        ggtitle("Population", subtitle="https://ec.europa.eu/eurostat/data/database (demo_fmonth)")

ggsave(plot=pdp1, file="pdp1", width=12)

url | Wed, 25/03/2020 08:51 | tagi: , , ,
Dzienne dane dot. wypadków drogowych w Polsce

Na stronie http://policja.pl/pol/form/1,Informacja-dzienna.html udostępniane są dzienne dane dotyczące liczby interwencji, zatrzymanych na gorącym uczynku, zatrzymanych poszukiwanych, pijanych kierujących, wypadków, zabitych w wypadkach, rannych w wypadkach.

Ściągam wszystkie dane:

#!/bin/bash

rm pp.html

for ((i=0; i <= 274; i++)) do 
  if [ ! -f ${i}.html ] ; then
    curl -o ${i}.html "http://policja.pl/pol/form/1,Informacja-dzienna.html?page=${i}" ; 
    grep 'data-label' ${i}.html >> pp.html
    sleep 6
  else 
    grep 'data-label' ${i}.html >> pp.html
    echo done
  fi

done

zamieniam prostymi skryptami na plik CSV, który ma następującą strukturę:

data;interwencje;zng;zp;znk;wypadki;zabici;ranni
2008-12-01;NA;873;344;447;135;1;1

okazuje się że liczba interwencji jest podawana od roku 2018, wcześniej nie była. Nic to wstawiamy NA.

Na przyszłość dane będą aktualizowane w ten sposób, że codziennie (przez odpowiedni wpis w pliku crontab) będzie pobierany plik http://policja.pl/pol/form/1,Informacja-dzienna.html:

#!/usr/bin/perl
use LWP::Simple;

$PP="http://policja.pl/pol/form/1,Informacja-dzienna.html";
$PPBase="pp.csv";

$content = get("$PP");

$content =~ s/\r//g; # dla pewności usuń

@content = split (/\n/, $content);

foreach (@content) { chomp();
  unless ($_ =~ m/data-label=/ ) { next }

  if ($_ =~ m/Data statystyki/ ) { $d = clean($_); }
  elsif ($_ =~ m/Interwencje/ )  { $i = clean($_); }
  elsif ($_ =~ m/Zatrzymani na g/ ) { $zg = clean($_); }
  elsif ($_ =~ m/Zatrzymani p/ ) { $zp = clean($_); }
  elsif ($_ =~ m/Zatrzymani n/ ) { $zn = clean($_); }
  elsif ($_ =~ m/Wypadki d/ ) { $w = clean($_);  }
  elsif ($_ =~ m/Zabici/ )  { $z = clean($_);  }
  elsif ($_ =~ m/Ranni/ ) { $r = clean($_);
    $l = "$d;$i;$zg;$zp;$zn;$w;$z;$r";
    $last_line = "$l"; $last_date = "$d";
    ## pierwszy wpis powinien zawierać dane dotyczące kolejnego dnia
    ## więc po pobraniu pierwszego można zakończyć
    last;
 }
}

### read the database
open (PP, "<$PPBase") || die "cannot open $PPBase/r!\n" ;

while (<PP>) { chomp(); $line = $_; @tmp = split /;/, $line; }

close(PP);

### append the database (if new record)
open (PP, ">>$PPBase") || die "cannot open $PPBase/w!\n" ;

unless ("$tmp[0]" eq "$last_date") { print PP "$last_line\n" }
else {print STDERR "nic nowego nie widzę!\n"}

close(PP);

sub clean  {
 my $s = shift;
 $s =~ s/<[^<>]*>//g;
 $s =~ s/[ \t]//g;

 return ($s);
}

Zaktualizowana baza jest wysyłana na githuba. Tutaj jest: https://github.com/hrpunio/Nafisa/tree/master/PP

Agregacja do danych tygodniowych okazała się nietrywialna

Niektóra lata zaczynają się od tygodnia numer 0 a inne od 1. Okazuje się, że tak ma być (https://en.wikipedia.org/wiki/ISO_week_date#First_week):

If 1 January is on a Monday, Tuesday, Wednesday or Thursday, it is in W01. If it is on a Friday, it is part of W53 of the previous year. If it is on a Saturday, it is part of the last week of the previous year which is numbered W52 in a common year and W53 in a leap year. If it is on a Sunday, it is part of W52 of the previous year.

Nie bawię się w subtelności tylko tygodnie o numerze zero dodaję do tygodnia z poprzedniego roku.

Sprawdzam czy jest OK i się okazuje że niektóre tygodnie mają 8 dni. W plikach html są błędy:

Błędne daty 2019-10-30 winno być 2019-09-30; podobnie błędne 2019-03-28 (winno być 2019-02-28), 2018-11-01 (2018-12-01), 2018-12-01 (2017-12-01), 2016-04-30 (2016-03-30), 2009-08-31 (2009-07-31). Powtórzone daty: 2016-03-10, 2010-07-25, 2010-01-10 (zdublowane/różne/arbitralnie usuwamy drugi) Ponadto brak danych z następujących dni: 2015-12-04--2015-12-07, 2015-04-17--2015-04-20, 2014-10-02--2014-10-05, 2014-01-23 i jeszcze paru innych (nie chcialo mi się poprawiać starych.)

Teraz jest OK, plik ppw.csv ma nast strukturę:

rok;nrt;interwencje;in;zng;zngn;zp;zpn;znk;znkn;wypadki;wn;zabici;zn;ranni;rn;d1;d7 coś co się kończy na `n' to liczba tego co jest w kolumnie poprzedniej, np zn to liczba dni tygodnia dla kolumny zabici. Generalnie kolumny kończące się na `n' zawierają 7 :-) Kolumna d1 to pierwszy dzień tygodnia a kolumna d7 ostatni.

maxY <- max (d$zabici)
pz <- ggplot(d, aes(x= as.factor(nrt), y=zabici )) + 
 geom_bar(fill="steelblue", stat="identity")  +
 xlab(label="") +
 ggtitle("Wypadki/zabici (Polska/2020)", subtitle="policja.pl/pol/form/1,Informacja-dzienna.html") 

W sumie agregacja jest niepotrzebna, bo można ją zrobić na poziomie R używając funkcji stat_summary:

pw <- ggplot(d, aes(x= week, y=wypadki)) + 
 stat_summary(fun.y = sum, geom="bar", fill="steelblue") +
 scale_x_date( labels = date_format("%y/%m"), breaks = "2 months") +
 xlab(label="") +
 #theme(plot.subtitle=element_text(size=8, hjust=0, color="black")) +
 ggtitle("Wypadki (Polska/2018--2020)", subtitle="policja.pl/pol/form/1,Informacja-dzienna.html") 

albo najpierw agregując dane a potem wykreślając wykres szeregu zagregowanego. Drugi sposób pozwala na przykład na dodanie linii oznaczających poziomy zagregowanego zjawiska/etykiety słupków w sposób `inteligentny'. Dodajemy etykiety (z numerem tygodnia) tylko dla słupków poniżej/powyżej Q1/Q3:

## agregowanie do danych tygodniowych kolumn ranni, zabici, wypadki
dw <- d %>% group_by ( YrWeek) %>% summarise_at ( vars(ranni,zabici,wypadki), sum )

## Obliczanie mediany i kwartyli
median.zw <- median(dw$zabici)
q1.zw <- quantile(dw$zabici, 1/4) 
q3.zw <- quantile(dw$zabici, 3/4) 

## YrWeekZZ to numer tygodnia, dla tygodni w których liczba wypadków jest typowa
## numer jest pusty (żeby nie był drukowany); taki trick może jest lepszy
dw$YrWeekZZ <- substr(dw$YrWeek,4,5)
dw$YrWeekZZ[ (dw$zabici > q1.zw) & (dw$zabici < q3.zw) ] <- ""

pz.2 <- ggplot(dw, aes(x= YrWeek, y=zabici)) + 
 geom_bar(stat="identity", fill = "steelblue") +
 geom_text(data=dw, aes(label=sprintf("%s", YrWeekZZ), x=YrWeek, y= zabici), vjust=-0.9, size=3 ) +
 geom_hline(yintercept=median.zw, linetype="solid", color = "violet", size=.4) +
 geom_hline(yintercept=q3.zw, linetype="solid", color = "red", size=.4) +
 geom_hline(yintercept=q1.zw, linetype="solid", color = "red", size=.4) +
 xlab(label="rok/tydzień") +
 ylab(label="zabici") +
 scale_x_discrete(breaks=c("18/01", "18/10", "18/20",  "18/30", "18/40",
          "19/01", "19/10", "19/20",  "19/30", "19/40", "20/01", "20/10"))  +
          #  labels = c("/18/01", "18/10", "18/20", "")) ## tutaj niepotrzebne
 ggtitle("Wypadki/zabici (Polska/2018--2020)", 
  subtitle="Linie poziomie: q1/me/q3 (źródło: policja.pl/pol/form/1,Informacja-dzienna.html)") 

url | Wed, 25/03/2020 07:29 | tagi: , ,
Dane nt #Covid19 podsumowanie

Dane pierwotne: Center for Systems Science and Engineering (CSSE/Johns Hopkins University) https://github.com/CSSEGISandData/COVID-19 (także słynna wizualizacja: https://gisanddata.maps.arcgis.com/apps/opsdashboard/index.html#/bda7594740fd40299423467b48e9ecf6.) European Centre for Disease Prevention and Control https://ecdc.europa.eu/en/geographical-distribution-2019-ncov-cases.

Dane agregowane od innych: Our World in Data/Coronavirus Source Data/WHO Situation Reports https://ourworldindata.org/coronavirus-source-data . Są też tzw. dane w czasie rzeczywistym: https://worldometers.info/coronavirus/, ale ich wiarygodność jest podejrzana, bo w przeciwieństwie do tych wyżej opisanych nie wiadomo jak są zbierane i/lub skąd agregowane (więc nie ma klikalnego linku).

url | Tue, 17/03/2020 05:12 | tagi: , ,
Pierwszy skazany w sprawie zabójstwa Adamowicza

Zaproszenie na własny pogrzeb?

Dariusz S., pracownik Agencji Ochrony Tajfun, która 13 stycznia 2019 r. zabezpieczała imprezę Wielkiej Orkiestry Świątecznej Pomocy, tuż po zdarzeniu zeznał, że nożownik, który zaatakował Adamowicza, wszedł na scenę posługując się plakietką z napisem `Media'.

`Oskarżony był pod wpływem bardzo silnych emocji, to nie było zaplanowane' -- uznał w piątek Sąd Rejonowy w Gdańsku, skazując 37-letniego mężczyznę na karę roku więzienia w zawieszeniu na trzy lata. Wymierzył mu też 7,5 tys. złotych grzywny oraz obciążył kosztami procesu w kwocie ponad 32 tys. zł. Wyrok nie jest prawomocny.

Sąd zwrócił uwagę, że u wszystkich, którzy widzieli tragiczne wydarzenie z 13 stycznia 2019 r. `rodziło się pytanie, jak to się stało, że sprawca zabójstwa prezydenta Gdańska po prostu wkroczył sobie na scenę, dokonał tego czynu, po czym jeszcze przechwycił mikron i wygłosił swoje oświadczenie'.

[TVPInfo 21.02.2020, 09:52 |aktualizacja: 10:34]

Koncert 27. Finału Wielkiej Orkiestry Świątecznej Pomocy na Targu Węglowym w Gdańsku rozpoczął się w niedzielę o godz. 15. `Światełko do nieba' zaplanowano jak w całej Polsce na godz. 20.

Organizatorzy -- stowarzyszenie Regionalne Centrum Wolontariatu w Gdańsku -- zgłosili, że w koncercie weźmie udział 5 tys. osób. Taka impreza, jak każda powyżej tysiąca osób, mogłaby zostać zarejestrowana jako masowa. Finał WOŚP zgłoszono jednak jako zajęcie pasa drogowego. Na podstawie takich przepisów organizowano ją w Gdańsku od początku, tak jak wiele innych wydarzeń sportowych czy kulturalnych. Tym razem też uzyskała zgodę magistratu [czyli zamordowanego -- moje] i komendanta wojewódzkiego policji.

Regionalne Centrum Wolontariatu wynajęło w tym celu Agencję Ochrony `Tajfun' z Gdańska. Jak zapewniają organizatorzy, miała ona potraktować wydarzenie tak jak imprezę masową.

Agencja Tajfun działa od 2008 roku. Ma licencję. Na Targu Węglowym pracowało w niedzielę 50 ochroniarzy.

-- Pod względem formalnym i praktycznym w naszej ocenie wszystko zostało dochowane -- mówił w poniedziałek na konferencji prasowej Łukasz Isenko, pełnomocnik firmy.

[https://trojmiasto.wyborcza.pl/; Anna Dobiegała, współpraca Aleksandra Brzezińska 16 stycznia 2019 | 05:02]

[Ten S. to nie jest szeregowy ochroniarz tylko nieformalny szef firmy zresztą -- moje]: Tajfun działa od 2008 roku. Posiada licencję wystawioną na nazwisko Gracjana Zwolaka, ale w portalach społecznościowych jako dyrektor zarządzający występuje Dariusz Sokołowski. To były policjant, kurator sądowy, a także właściciel firmy windykacyjnej. Tajfunem zarządzać ma od półtora roku. [WirtualnaPolska]

Dariusz S. to były policjant. Pracował m.in. w Komendzie Miejskiej w Gdańsku. Jak ustalił portal tvn24.pl, odszedł ze służby ze względu na bójkę, do której doszło w Gdańsku 29 lipca 2016 roku. Akt oskarżenia trafił do sądu w sierpniu 2017 r., ale proces jeszcze się nie rozpoczął. Z nieoficjalnych informacji portalu wynika, że Dariusza S. zawieszono w obowiązkach policjanta, gdy usłyszał zarzuty.

[WirtualnaPolska 21.01.2019, Dariusz S., który ochraniał tragiczny finał WOŚP, był oskarżony o pobicie i groźby. Musiał odejść z policji]

Teraz dostał wyrok w zawieszeniu, bo miał zdaniem sądu: poświadczony dokumentami wzorowy przebieg służby w policji.

To chyba wszystko.

url | Mon, 24/02/2020 21:35 | tagi: , , ,
Wycieczka do Paryża

Katharina von Gail

vanGogh (autoportret)

Soldats français en marche

Lądowanie w piątek na lotnisku w Beauvais, za 13 EUR (od osoby) jedziemy mikrobusem na stację metra Porte Maillot. Tu kupujemy bilety (i takie ciastko co wygląda jak sernik, ale jest z przesłodzonego budyniu) i jedziemy zwiedzać Luwr. Około 21 jedziemy (także metrem) na kwaterę wynajętą przez AirBnB w 13 dzielnicy. Od stacji Olympiades nasza kwatera jest może 300 m. W Luwrze to najbardziej mi się podobają eksponaty z bliskiego i środkowego wschodu (Syria/Iran/Irak) oraz (bo lubię) kolekcja malarstwa holenderskiego (Breugel itp.)

Rano pobudka i około 9:00 idziemy zwiedzać miasto rozpoczynając od Notre Dame, które jest oczywiście po pożarze zamknięte. Oglądamy to co widać zza parkanu. W centrum koncentracja policji w pełnym rynsztunku bojowy, ale się nie biją. Chodzimy, oglądamy około 15:00 idziemy do muzeum Orsay oglądać francuski symbolizm. Oglądamy do 18:00 czyli do zamknięcia. Potem na kwaterę. Odkrywamy, że w pobliżu naszego bloku jest m.in supermarket, piekarnia i chińska restauracja. Decydujemy się na kolację w tej restauracji wydając prawie 40 EUR.

Game day czyli niedziela. Rozpoczynamy od oglądania Sorbony (nic ciekawego), potem idziemy pod Panteon. Wejście płatne więc my nie wchodzimy, ale Janek ma za darmo jako osobnik małoletni (26 lat). Czekamy na niego w kościele St Etienne du Mont załapując się na mszę. Msza jest na wysokim poziomie (w sensie formy--organista wirtuoz, śpiew pod kierunkiem zawodowej śpiewaczki ewidentnie itp). Kościół pełny i sporo młodych ludzi, w większości białych. Po mszy idziemy na naleśnika, zwiedzamy coś tam jeszcze i jedziemy metrem do Saint Denis.

Metro pełne ludzi. Jadą na mecz rugby Francja-Włochy. Wysiadamy, idziemy z kibicami oglądać stadion. Potem pod Bazylikę, bo to blisko. Wejście do kościoła jest za darmo, ale do krypty z Karolem Młotem już nie (10 EUR). Przed Bazyliką karuzela. Hmmm coś jakby ktoś na Wawelu przed kryptą królów postawił wesołe miasteczko. Zresztą następnego dnia nasz Francuz z kwatery pyta gdzie byliśmy. -- W Saint Denis, -- Na meczu? -- Nie oglądać stadion i katedrę -- Jaką katedrę?

Ostatni dzień: Pola Elizejskie, Łuk Triumfalny, Pałac Macrona, plac Trocadero (jeszcze jeden naleśnik, tym razem nie na talerzu, ale z foodtrucka), Wieża Eiffla, pałac Inwalidów (ale tylko z zewnątrz; zwłoki Napoleona sobie darowaliśmy a na muzeum Armii nie było czasu). Coś tam jeszcze zwiedzamy i jedziemy na stację metra Porte Maillot na 17:00. Zresztą od 16:00 już pada. Dwie godziny jedziemy na lotnisko, bo są korki, ale samolot do GDA też się spóźnił. Odlatujemy z Paryża o 9:00 wieczorem z 30 minutowym opóźnieniem.

Podsumowanie: Z muzeów to zwiedziliśmy Luwr i Orsay. Obejrzeliśmy z 10 kościołów w tym Bazylikę Saint Denis i stadion. Paryż zrobił na mnie nadspodziewanie dobre wrażenie. Sprawne metro, ciekawe muzea, w których zbiory są przyjaźnie wyeksponowane dla zwiedzających, że tak powiem: żadnych szyb czy barierek (za wyjątkiem kilku już naprawdę unikatowych eksponatów takich jak Mona Lisa. można podjeść i palec wsadzić w płótno vanGogha czy Breugla). Nie ma wałęsających się uchodźców jak w Mediolanie a wszyscy bezdomi jakich widzieliśmy to biali. Dużo policji/wojska z bronią maszynową ma ulicach.


Od lewej: pałac Dariusza w Luwrze/regaty w Molesey/kibice Włoscy/St. Denis (grobowce i katedra)

Koszt (3 osoby): 900 PLN kwatera, luwr+orsay 230+125 PLN, metro 200 PLN, przejazd z/do Paryża 300 PLN, bilety lotnicze 800. Razem wychodzi jakieś 2500 PLN. Do tego jeszcze kilkaset złotych na jedzenie. W 3 kaflach się zmieściliśmy myślę...

Do pobrania ślady kml ze zdjęciami; album ze zdjęciami.

url | Mon, 17/02/2020 05:36 | tagi: , , ,
Ciasto karobowe

Karob w postaci strąków zobaczyłem pierwszy raz w życiu w zeszłym roku w Adanie (zapakowany w sklepie, nie na drzewie). Indagowany na okoliczność co to jest, poznany tam Turek, powiedział mi, że oni to żują, ale można to też jeść. Na spróbowanie kupiłem jedną paczkę, która długo leżała w szafie, ale w końcu ją zjadłem i całkiem mi smakował. Zachęcony, zbadałem głębiej temat przy pomocy google no i natrafiłem m.in. na przepis na proste ciasto z karobu (tutaj):

Składniki (na jedną keksówkę 20x11cm): 1/2 szklanki i dwie łyżki (160g) mąki pszennej; 1/3 szklanki karobu (50g); 1 duży banan; 1/4 szklanki brązowego cukru (ja dałem 40g ksylitolu); 1/2 szklanki oleju (80g); 1/3 szklanki mleka roślinnego (ja lałem tyle mleka/wody żeby ciasto miało właściwą konsystencję); szklanka orzechów włoskich*; pół szklanki żurawiny; łyżeczka proszku do pieczenia; łyżeczka sody.

Drobna uwag: autor cytowanego bloga BTW rąbnął się i raz pisze laskowych a raz włoskich. Ja dałem włoskich m.in. dlatego, że w moim rankingu orzechów laskowe są na samym końcu.

Przygotowanie: zmieszać wszystko za wyjątkiem żurawin/orzechów, a banana zmienić na miazgę uprzednio. Dodać żurawiny i orzechy od masy. Zamieszać. Piec przez 30--35 minut (ja tam zawsze piekę na papierze, bo nie chce mi się myć formy:-)

Czyli super prosto a ciasto jest bardzo dobre...

url | Mon, 27/01/2020 06:13 | tagi: , , ,
Podsumowanie poprzedniego roku rowerowego


Podsumowanie zacząłem od wsadzenia (wreszcie) całego dorobku na githuba. Są tam detaliczne dane od 1993roku (27 lat, nie bójmy się słów); do tego w latach 1990--92 przejechałem 20,760, ale ten wyczyn nie jest, aż tak detalicznie udokumentowany. Razem wychodzi w latach 1990--2019 (30 lat) 242,355 km. Czyli do 250 tysięcy zostało 7645 km. Dam radę (jak zdrowie nie przeszkodzi)...

Na githubie jest w szczególności plik opus_magnum.csv, który zawiera cztery kolumny: dd;mm;yyyy;dist (dzień, miesiąc, rok oraz dystans; czasami dni mogą się powtarzać--to nie jest błąd, tylko oznacza, że jeździłem kilka razy dziennie):

require(ggplot2)
require(dplyr)

d <- read.csv("opus_magnum.csv", sep = ';', dec = ",",  header=T, na.string="NA");

dm <- d %>% mutate(cat = factor(yyyy)) %>%  group_by (cat) %>%
  summarise( tdist = sum(dist, na.rm=TRUE) /1000 ) %>%
  as.data.frame
  
yyyy.first <- first(dm$cat)
yyyy.last <- last(dm$cat)

time.period <- sprintf ("%s--%s", yyyy.first, yyyy.last)

p.m <- ggplot(dm, aes(x = cat, y = tdist )) +
    ggtitle(sprintf ("Distance by year (%s)", time.period)) +
    xlab("year") + ylab("ths km") +
    geom_bar(position = 'dodge', stat = 'identity', fill = "steelblue") +
    geom_text(data=dm, aes(label=sprintf("%.2f", tdist), y= tdist),
    vjust=1.5, color="darkblue", size=3 )
ggsave(p.m, file="opus_magnum.pdf", width=12)
### ###
cy <- 2019
d <- d %>% filter (yyyy == cy) %>% as.data.frame

rides = nrow (d)
total = sum (d$dist)
mride = mean (d$dist)

dm <- d %>% mutate(cat = factor(mm)) %>% group_by (cat) %>%
  summarise( ss = sum(dist, na.rm=TRUE)) %>%
  as.data.frame

p.m <- ggplot(dm, aes(x = cat, y = ss )) +
ggtitle(sprintf ("Cycling in %i (total: %.1f kms/ %i rides/ %.1f kms per ride)",
   cy, total, rides,  mride)) +
    xlab("month") + ylab("km") +
    geom_bar(position = 'dodge', stat = 'identity', fill = "steelblue", alpha=.5) +
    geom_text(data=dm, aes(label=sprintf("%.0f", ss), y= ss),
    vjust=1.5, color="white" )

p.m

outfile <- sprintf ("opus_%i.pdf", cy)
ggsave(p.m, file=outfile, width=10)

Wyniki obok.

url | Sat, 04/01/2020 21:16 | tagi: ,
Rok białego konia

Czyli Tuska vel ostatniej nadziei białego człowieka. Wpis nie tyle prześmiewczy co pro memoria.

Upływający rok był rokiem aż dwóch wyborów w Polsce (majowe do PE; jesienne do Sejmu). Dwóch a w zasadzie trzech, bo chociaż wybory prezydenckie odbędę się w maju 2020, to wiadomo było że kampania do nich zacznie się już po wyborach do Sejmu 2019, a w zasadzie to wybory do Sejmu będą częścią kampanii prezydenckiej.

Z kolei wybory do PE (nominalnie mało ważne z uwagi na kompetencje PE) były o tyle istotne, że w powszechnej opinii anty-PiSowa opozycja miała mocny handicap: miastowi głosują chętniej w tych wyborach wieś ma je głęboko. Przegrana PiSa mogła odwrócić kartę a szansa na to była duża...

Konia wykład majowy

Do tego Koń (czyli Tusk) miał być prawdziwą Wunderwaffe zjednoczonej opozycji. Oczekiwania sympatyków opozycji były takie, że po wystąpieniu Tuska (3 maja), PiSowcom majtki spadną z wrażenia, a ich herszt Kaczyński sam zrezygnuje i poprosi o najmniejszy wymiar kary.

Z jakiś powodów wszystko poszło nie tak. Co mówił Tusk nikt nie pamięta, co mówił bliżej nieznany wcześniej 40-letni czerwony Hunwejbin, no prawie wszyscy pamiętają. Że kościół to świnie itp... Jest teoria, że tym wystąpieniem faktycznie Tusk mocno pomógł, ale PiSowi... NB. wbrew oczywistym faktom, że event był mega-klapą wszystkie antypisowe szczekaczki przez czas jakiś usiłowały wmówić swojej widowni że nie, nic podobnego. Że prawdę powiedział, że PiS ma problem itp...

Konia Ruch, którego nie było

Potem były wybory i mega-wpierdol. Koalicja, która jedyne co osiągnęła w powszechnej opinii to, że wyniosła kilku prominentnych, mocno wiekowych SLDowców do godności MEPa się rozpadała, a Koń walczył dalej. Celem Konia tym razem miało być (wg usłużnych mediów bo czy wg. samego Konia to już nie jest pewne) zakładanie partii (na jesienne wybory; cf Ruch 4 czerwca: Nowa platforma Donalda Tuska )... W atmosferze uświadomienia sobie klęski majowej, odpowiedzialności za to Schetyny (który ani myślał rezygnować--inna sprawa że PO po Tusku to kadrowa wydmuszka, i lepszych od Schetyny to tam nie ma) Tusk znowu miał być młotem na PiS (że dał dupy w maju nikt już nie chciał pamiętać i że pomysł nowej partii padł już w lutym czyli przed majową kompromitacją Konia, co jakby zmniejszyło znacząco siłę nazwijmy to przyciągającą do tej inicjatywy) -- przyjedzie, zjednoczy lepszą Polskę, wygra... Startem do tego miały być obchody 30-lecia 4-czerwca (tzw. pierwszych wolnych wyborów).

Od początku wiało lipą co źle wróżyło Koniowi: hasło obchodów mocno fałszywe, bo wybory nie były wolne jak wiadomo. Do tego lokalne PO w osobie p. Bidulkiewicz zafundowało chuj-wi-po-co stół za 150 tysiaków, imitację niby tego co było w 1989 r. Nic tak bardzo ludzi nie wkurwia, jak takie wydatki. Generalnie była to impreza pn. zastaw-się-a-postaw-się (albo minimum treści maksimum formy). Braki w rozdętym programie zapełniał kto chciał aby tylko miał prawidłowy przekaz, a nie PiSowy, łącznie z bliżej nieokreślonym pastorem z Kielc, czyli kolejną wizerunkową mega-wpadką chętnie nagłaśnianą przez przeciwników Bidulkiewiczowej (cf Edward Ćwierz -- pastor, prezes Fundacji Pojednanie i główny organizator trzydniowych wydarzeń, które zaplanowano w naszym mieście między 30 sierpnia a 1 września jest głęboko poruszony złymi interpretacjami, które są szeroko komentowane przez polityków PiS i media; Przesłanie Marszu Życia)

I znowu chuj-z-tego-Koniowi-wyszło... Coś tam bredził, co--nikt nie pamiętał po tygodniu... Pierwszą gwiazdą imprezy na tle gamoniowatego Komorowskiego, błazna-Wałęsy, ww. głównego organizatora Ćwierza i wycofanego Tuska okazał się król-estrady Kwaśniewski, który m.in. kpiąco obwieścił że świętuje 30-lecie swojego obalenia (czy jakoś tak)... Platformiane media ćwiczące swoją widownię znowu udawały, że w zasadzie wszystko poszło, no może nie idealnie, ale na pewno PiS na tym stracił.

Konia kampania jesienna

Paradoksalnie nastroje przed wyborami jesiennymi były wśród antyPiSu chujowe i generalnie spodziewano się ostrego lania (którego nie było). Miarą chaosu może być popieranie przez Wałęsę PSLu (a Kosiniaka odcinania się od tego poparcia, w ewidentnej obawie, że takie poparcie -- było nie było legendy-czegoś-tam -- dziś to tylko może zaszkodzić) albo nominowanie Kidawy-Błońskiej jako #1 w okręgu 19 w ostatniej chwili... Tusk odpuścił, bo pewnie też oceniał, że będzie łomot, a kto by chciał być kojarzony z klęską, na pewno nie on--urodzony zwycięzca.

A tymczasem, a może dlatego, że zabrakło tym razem młota-na-PiS, wynik dla opozycji był nadspodziewanie dobry. Tak dobry, że uzasadnione jest pytanie: gdyby nie nastrój zniechęcenia, słabe przywództwo, zła strategia/taktyka (pójście w Jachirowanie jako jedyna partia tych wyborów) itd/itp, to jest więcej niż pewne, że PiS by stracił większość nie tylko w Senacie ale i w Sejmie. Uzasadnione jest także pytanie czy działalność Konia pomogła PiSowi zachować tę większość? Moim zdaniem tak. Chaos jaki generował nie ułatwiał...

Mając na uwadze powyższe dziwić może, że ktoś uważał Tuska za poważnego kandydata na urząd prezydenta. Że uważał to jeszcze pół biedy, ale że uważał w listopadzie to już źle świadczy. Zresztą jak w końcu podkulił ogon, no to oczywiście słusznie wybrał (wg. wyznawców). Przecież przewodniczenie zoombie-partii (takie to ważne stanowisko jest, że nikt z wyznawców Konia nie jest w stanie podać nazwisk wcześniejszych przewodniczących tej Europejskiej partii) jest dużo bardziej prestiżowe niż urząd prezydenta RP (ja na przykład potrafię wymienić wszystkich, którzy go pełnili przed Dudą). Jedyne co zrobił to opóźnił wybór kandydata PO...

Konia obrona sądów

O tym, że Koń się stacza świadczy jego aktywność grudniowa. Zamiast odpuścić, zajął się (wreszcie) obroną praworządności w PL. Śliski temat zresztą dla Konia, bo to za jego premierowania było kilka głośnych spraw przetrzymywania przez sądy w aresztach Bogu-ducha-winnych ludzi w tym a zwłaszcza tzw. kiboli (Maciej Dobrowolski).

No więc pojawił się wreszcie pretekst w postaci animowania zdychających (frekwencyjnie) prostestów przed Sądami. I co? I nie przyszedł. Ochwacił się...

A miał 500m w linii prostej od tych co na niego czekali. Książkę podpisywał.

Podsumowanie

Cztery razy wpiernicz czyli raz na kwartał. Jego była partia, jedyne co osiągnęła to wypromowała SLD -- prawdziwego wygranego 2019r. Brawo...

url | Thu, 26/12/2019 16:35 | tagi: , ,
Banany w cieście

Banany w cieście serwują w restauracji Lotos w Kwidzynie. Podają je na gorąco obłożone bitą śmietaną. Ponieważ nie wydaje się to specjalnie skomplikowana potrawa postanowiłem sam coś takiego wykonać.

Składniki (cf. https://www.domowe-wypieki.pl/przepisy/desery/125-smazone-banany-w-ciescie): 50 g mąki pszennej; 20 g wiórków kokosowych (= 3 łyżki); 100 ml mleka; 2 jajka; 2 łyżeczki cukru waniliowego; 1/2 łyżeczki proszku do pieczenia; szczypta soli; olej do smażenia; cukier puder do posypania

Powyższe zmodyfikowałem: nie dałem wiórków i zamiast 2 łyżeczek cukru waniliowego, 1 łyżeczkę zwykłego pudru.

Wykonanie: Składniki zmiksować. (Ciasto powinno być dość gęste, aby utrzymywało się na bananie). Banany przekroić wzdłuż na pół. Kawałki bananów zanurzać w cieście. Smażyć na głębokim oleju, z dwóch stron, do zarumienienia. Usmażone banany wykładać na ręczniki papierowe, aby ociekły z tłuszczu. Gotowe posypać cukrem pudrem.

Nie miksowałem ale widelcem i też masa wyszła całkiem gładka. Nie przekroiłem też wzdłuż -- następnym razem spróbuję. Ale i tak wyszły bardzo dobre. Zamiast cukru pudru polewam jogurtem albo dodaję trochę serka waniliowego i trochę suszonych owoców (żurawin na przykład)

url | Sun, 24/11/2019 21:15 | tagi: , ,
Odessa -- ostatnia wycieczka w roku

Tour de Ost 2019 odcinek ostatni (szósty). Byłem już w Uzbekistanie, Turcji, Ukrainie, Gruzji i Rumunii (to też trochę na wschód). Teraz jeszcze raz na Ukrainie, w Odessie konkretnie. Ryanair otworzył połączenie GDN-Odessa od 2 listopada 2019. My (ja z Elką) tym pierwszym lecimy licząc, że będzie coś w rodzaju przywitania pierwego pasażyra Rusfłota (z filmu Machulskiego Deja Vu, w którym Stuhr gra zawodowego mordercę wysłanego do Odessy z Chicago); ale nie było żadnego przywitania.

Po wylądowaniu jedziemy trolejbusem z lotniska pod dworzec kolejowy. Stamtąd piechotą na kwaterę, która jest jakie 200 m w linii prostej od schodów Potiomkina-Eisensteina. Docieramy na miejsce już po zmroku. Zostawimy bambetle i idziemy na miasto. Zwiedzamy słynną ulicę Deribasowską i oglądamy Operę. To wszystko jest blisko siebie zresztą...

Rano rozpoczynamy zwiedzanie od portu i schodów. Potem znowu Opera za dnia. Idziemy do muzeum sztuki nowoczesnej (bez szału i dość małe, ale parę ciekawych rzeczy jest z czołgiem z tektury na czele), a potem schodzimy na plażę (bo to blisko jest). Wracamy do domu i idziemy na obiad do (podobno #1) lokalu pn. Kumanets na barszcz ukraiński i pierogi. Tanio nie wyszło... Jemy obiad w trójkę bo umówiliśmy się ze znajomym Ukraińcem JS (poznany w Bachotku), z którym pójdziemy też do Opery. Grają Romeo i Julię Prokofiewa. Opera zresztą jest imponująca a wśród widzów jest wielu Polaków... No proszę tak źle z kulturą wysoką nie jest w PL się okazuje...

Następnego dnia jedziemy oglądać twierdzę Akerman. Pociągiem ponad 2 godziny, powrót trochę krótszy bo jakieś 1,5h, ale za to trzęsie. Że pociąg regionalny, to nie musimy paszportów pokazywać przy kupnie biletów (poprzednio jak jechałem dwa razy pociągiem na Ukrainie to bez paszportu nie wpuszczali do wagonu). Po drodze na kwaterę idziemy do tatarskiej restauracji oczywiście na czebureki, które w życiu może jadłem ze dwa razy. Da się zjeść, ale żeby to jakiś miał być przysmak to też nie. Lokal BTW elegancki i oprócz czebureków dużo innych specjałów.

Ostatni dzień rozpoczynamy od zwiedzania bazaru koło dworca kolejowego. Wrażenie robi dział rybny. Mięsny to też egzotyka, ale podobny już widziałem w Gruzji czy w Uzbekistanie. NB znajdujemy na bazarze uzbecką piekarnię i kupujemy dwa uzbeckie chleby Non świeżo upieczone i gorące... Wracamy na kwaterę, zabieramy plecaki, idziemy na Uniwersytet odwiedzić JS. Potem już w stronę dworca... Robi się ciemno więc jedziemy na lotnisko. Koniec wycieczki. Bilety lotnicze w dwie strony były po 300 PLN, kwatera za 250 PLN, a bilety do Opery po 50 PLN (najlepsze miejsca).

Do pobrania ślady kml ze zdjęciami; album ze zdjęciami.

url | Tue, 19/11/2019 08:56 | tagi: , , ,
Taśmy Neumana czyli chujowe taśmy season 2019

Czemu chujowe taśmy to tutaj jest objaśnienie.

Tych z 2019 (tamtych sprzed 5 lat też zresztą) nie słuchałem w całości. Zresztą nie wiadomo co to jest całość.

Z tego co słyszałem (rzygam Tczewem/Tczewiacy to pojeby) taka specyficzna mobilizacja lokalnych działaczy. Że łudząco podobno do stosowanej w mafii to już inna sprawa (Naucz się tego, jak będziesz o czymkolwiek rozmawiał. Jak będziesz w Platformie, będę cię bronił, kurwa, jak niepodległości. Jak wyjdziesz z Platformy, to masz problem), albo inaczej cosaNostra (literalnie: wspólna sprawa) to Platforma w tym przypadku.

Ponadto ci niektórzy którym się wydaje, że popierają lepszą stronę mocy (nowoczesną/europejską/wykształconą itd) gdyby myśleli (a już dawno tego nie robią), to powinni być mocno zdziwieni co robi u boku p. Neumana wdowa po P. Adamowiczu. W oficjalnej wersji przecież św Paweł to niewinna ofiara PiSoskiego hejtu, a wg pana Neumna, no mówiąc oględnie średnio uczciwy typ żeby nie powiedzieć przestępca (Jedynym gościem jest Adamowicz, który ma absolutnie mega twarde rzeczy, które mogłyby go wyprowadzić w kajdankach). Zresztą wdowa Magdalena PecuniaNonOlet Adamowicz bezczelnie indagowana nt. ww. fragmentu zaapelowała o zmianę języka debaty oczywiście.

No i słusznie bo: Nasz elektorat, ten antypisowski, uzna, że to jest kurwa, atak PiS-u, żeby go zabić. I pójdą jeszcze bardziej na niego.

W tym przypadku na nią oczywiście.

Nb. pan SIENKIEWICZ Bartłomiej Henryk startuje do Sejmu z ramienia Koalicji Obywatelskiej w okręgu 33 (Kielce). Ma numer 1 na liście więc w zasadzie wejdzie na 100%.

url | Sun, 06/10/2019 06:56 | tagi: , ,
Stół Bidulkiewicz czyli inna Polska w praktyce

Będziemy jeździć z tym okrągłym stołem po Polsce. Jest w częściach, całego pewnie nie damy rady wozić, ale ma różne konfiguracje, instalacje. Już o tym rozmawialiśmy z organizacjami społecznymi i z samorządowcami -- powiedziała Dulkiewicz w porannej audycji w TOK FM. Będziemy jeździć po Polsce i rozmawiać, przekonywać, że inna Polska jest możliwa -- dodała.

Powyższe było w czerwcu. W międzyczasie o ile mi wiadomo nigdzie ze stołem nie byli. We wrześniu natomiast:

0. Agitując za udziałem w tzw. Budżecie Obywatelskim twierdziła, że sama już zagłosowała.

1. Dziennikarz z lokalnego trojmiasto.pl zagłosował za nią udowadniając, że internetowy system do głosowania jest do dupy (i/lub nieprawdą jest że zagłosowała)

2. Rzecznik prasowy Bidulkiewicz -- realizując program innej Polski zapewne -- groził dziennikarzowi zawiadomieniem o popełnieniu przestępstwa

3. Szef trojmiasto.pl pokajał się publicznie (wolne media to te które przepraszają władzę przynajmniej w innej Polsce)

4. Sama Bidulkiewicz wycofała się z zawiadomienia (a miała inne wyjście?) wydając głupi i pompatyczny manifest (czyli zachowując się normalnie i w swoim stylu z naciskiem na głupio):

Moje zdanie na temat roli wolnych i niezależnych mediów w demokratycznym państwie prawa i współuczestniczenia w budowie społeczeństwa obywatelskiego jest powszechnie znane. [...] Dziennikarze patrzą nam, samorządowcom, urzędnikom, politykom na ręce. Jest to słuszne i potrzebne. Dziękuję panu redaktorowi naczelnemu Michałowi Kaczorowskiemu za refleksję na temat granicy tego, co jest konieczne, i tego, co jest naruszeniem prawa. To publiczne uznanie, że nie powinno się nadużywać prawa jest ważne. W moim odczuciu jest to wystarczające, by z powodów opisanych powyżej nie wchodzić na drogę prawną w związku z bezprawnym użyciem moich danych osobowych.

Więc jakby nie było przeproszenia to co by było? No i co z tą rolą wolnych mediów w innej Polsce w takim przypadku?

url | Fri, 27/09/2019 06:58 | tagi: , ,
Bodrum/Adana 2019

Ostatni odcinek moich wiosennych wojaży. Byłem w Uzbekistanie, potem w Turcji, Gruzji i na koniec w Połtawie (Ukraina). Wszystko już opisałem za wyjątkiem Turcji...

Przylot do Bodrum z opóźnieniem o 1 w nocy. Cały samolot jest upychany do autobusów, które zawiozą nas do różnych hoteli. Nasz hotel jest najdalej od lotniska więc zanim dojechaliśmy i zanim nas odprawili w recepcji jest już 3 rano. Można iść spać, ale my idziemy na śniadanie o 4 rano. Tak w ogóle mamy tu wykupiony pobyt pn all-inclusive-ultra czyli 6 posiłków na dobę w cenie, w tym jedzenie o północy i o czwartej nad ranem (poza tym śniadanie, późne śniadanie, obiad, kolacja). Są jeszcze opcje płatne, ale te w większości jeszcze niedziałające (przed sezonem jest?) Pierwszy raz biorę udział w czymś takim (człowiek uczy się całe życie)

Pobyt zaczyna się od spotkania z rezydentką z biura, które nas tutaj ściągnęło że tak powiem. Sympatyczna pani przedstawia wykaz atrakcji, w tym wycieczek po okolicy, z których możemy (za opłatą) skorzystać, z czego nas interesuje wyspa Kos i Pamukkale. Na Kos jest stąd o rzut beretem i pojedziemy jutro za 27 EUR. Z Pamukkale jest natomiast problem. Po pierwsze daleko, po drugie zorganizowane wycieczki tam są tylko w poniedziałki, My w poniedziałek jedziemy do Adany.

Po spotkaniu idę na śniadanie. Ale śniadania już nima. Spóźniłem się. Sześć posiłków w podanych terminach, ale pomiędzy kuchnia nie działa. He trudno...Na szczęście wszędzie są stoły z ciastkami więc zamiast śniadania jem te ciastka. Potem idę do Bodrum. Jest niby autobus, ale wolę się przejść. W Bodrum idę na dworzec autobusowy i się pytam o to Pamukkale. Jest normalny rejsowy autobus o 9:00 za 43 PLN w jedną stronę. Pięć godzin i się jest na miejscu (prawie). Mówię do kasjera, że słabo to widzę, a on że wcale nie, że na miejscu się jest około 14:00 a ostatni autobus powrotny jest o 19:00 więc spokojnie się wszystko obejrzy. No niby tak, tyle że 10h w autobusie brzmi przerażająco...

Oglądam Bodrum, wracam też piechotą (18.0 km razem wyszło wte-i-we-wte). Spotykam po drodze rezydentów z polskich biur podróży, których widziałem rano w hotelu. Mówią, że śmiało można jechać. Autobus będzie wygodny.

Spóźniam się na obiad też, więc zamiast obiadu znowu ciastka, bo wszędzie są stoły z ciastkami. Potem się okazuje, że to jakaś turecka konferencja była i to były ich ciastka a nie hotelowe (nigdy więcej nie było ciastek wystawionych non-stop). Jedzenie co do zasady tylko w godzinach wydawania posiłków. Pomiędzy posiłkami tylko napoje (w tym wyskokowe).

W sobotę (27.04) jedziemy na Kos wodolotem. Wysiadamy z wodolotu i pierwsze co robię to pożyczam za 5EUR rower. Objeżdżam Kos do połowy (65 km mi wyszło), wracam około 16:00. Nigdzie śladu słynnych uchodźców, nawet smrodu po ich nie ma...

W niedzielę (28.04) z kol. Karolem rano jedziemy na autobus do Pamukkale. Nie mamy kupionego biletu to się umawiamy na 7:00 na śniadaniu z zamiarem dojechania pierwszym autobusem o 7:30 do Bodrum. Kupujemy bilety bez problemu, jedzie z nami dosłownie kilka osób. Po drodze trzy razy dostajemy batony/herbatę i wodę. Autobus jest klimatyzowany. Standard lepszy niż w Wizzair. Dojeżdżamy do Denizli. Potem mikrobusem do Pamukkale (blisko 15km). Wszystko idzie jak po maśle: wchodzimy na górę, oglądamy wszystko co trzeba. Idziemy na obiad. Wracamy do Denizli, potem autobusem o 19:00 do Bodrum. Tym razem jest komplet i bardzo ciasno, ale na szczęście w Yatagan połowa wysiada. Robi się luźniej i nawet zasypiam. Kurcze od 6:00 na nogach...

Ktoś mnie budzi. Policja. Kontrola dokumentów na rogatkach Bodrum, do którego dojeżdżamy zgodnie z planem przed północą. Chcemy jechać taksówką do hotelu, ale się okazuje, że jest autobus. Po 24:00 jesteśmy z powrotem, cała wycieczka trwała 17h z czego jakieś 12h w autobusach. Żebym się nie dopytał to byśmy nawet nie wiedzieli, że można pojechać do Pamukkale nie tylko w poniedziałek i za pół ceny (ale się nie dziwię przewodnikom/rezydentom, ostatecznie oni są od sprzedawania a nie od darmowej akwizycji na rzecz konkurencji.)

Następnego dnia (29.04) jedziemy po śniadaniu na lotnisko i jeszcze przed południem jesteśmy w Adanie. Oficjalna część pobytu: Adana University. Wiozą nas autobusem do hotelu, potem zwiedzanie miasta i na koniec kolacja (kebap). Kolejny dzień zwiedzanie Uniwersytetu. Nowoczesna szkoła, robi dobre wrażenie. Tylko studentów dziwnie mało. Mówią, że 2 tys. U nas w PL by wlazło 20 tys...

Po zwiedzaniu Uniwersytetu obiad (znowu kebap). Współtowarzysze wyjazdu sobie życzą pojechać na zakupy do sklepów, więc jedziemy na przedmieścia. Wielkie galerie jak w PL... Eeee nic tu po mnie myślę, wrócę piechotą do hotelu. No i wracam. Galerie światowe, potem nowoczesne osiedla (często jeszcze niezasiedlone) no a potem slamsy aż do centrum. Kilometry slamsów...

Powrót do Bodrum. Idę znowu na miasto. Kupuję parę suwenirów i wracam. Przebojem jest torba z Kamlem Ataturkiem. Turcy są zachwyceni, że coś takiego noszę...

Rano na lotnisko (02.05). Trochę jakby wcześniej niż trzeba, ale szybko się okazuje dlaczego: autobus jeździ w odwrotnej kolejności po hotelach, a że my najdalej od lotniska to zaczął od nas. Wylot do tego się dramatycznie opóźnił. Nawet nam rozdali jedzenie na koszt firmy. Przed północą w GDA (zamiast 19). Potem pół godziny czekania na walizę (bagażowi sobie poszli?) Wreszcie jestem w domu. O północy, ale warto było....

Spisane 16.8.2019 w samolocie do Cluj. Ciekawy wyjazd, ale jakoś nie mogłem się zebrać i go podsumować. Pierwszy raz w Turcji byłem zresztą.

Zdjęcia z wyjazdu są tutaj; ślad (ze zdjęciami) jest zaś tutaj (albo do pobrania (bez zdjęć) w formacie GPX.)

url | Thu, 05/09/2019 19:49 | tagi: , ,
Powrót z Cluj-Napoki

W zeszłą środę (28/08) wróciliśmy z Elką z wycieczki po Transylwanii. Bombardierem Q400 z Cluj-Napoki do Warszawy. Potem tym samym z Warszawy do Gdańska. Pierwszy raz leciałem Bombardierem BTW.

Z Cluj do W-wy obyło się bez większych przygód. W Warszawie komunikat że będzie opóźnienie. Najpierw że 10 minut, ostatecznie wyszło 40. Do tego jak już byliśmy w autobusie czekając na odjazd wkroczył pan z LOTu i odczytał 5 nazwisk (w tym dwa ewidentnie rosyjsko brzmiące). Nikt nie zareagował... Zamknęli drzwi i pojechaliśmy do samolotu. Wśród pasażerów extra załoga w pełnym rynsztunku, do tego kapitanem tej załogi Murzyn. Ciekawostka...

Wreszcie start o 20.25 (zamiast 19:40). Do Warszawy lot jest krótki, więc ledwo dali Grześka już zapowiadają lądowanie. Z nudów włączyłem GPSa w smartfonie, żeby sprawdzić czy będzie działał w Bombardierze (w Airbusach mi nie działa). Działa, więc widzę gdzie lecimy, na jakiej wysokości i z jaką prędkością. Mijamy Tczew. Tak nad Pruszczem zachrobotało: Cabin crew 4 minutes, ale zaraz potem wciągnął podwozie i minął GDN Rębiechowo na 900mnpm. Poleciał na Kartuzy.

No fear, skręci w lewo, okrąży Żukowo i spróbuje jeszcze raz (tak sobie myślę). Ale ten nie skręcił w lewo tylko w prawo, na Wejherowo i nabiera wysokości. 1600 mnpm. Do Szwecji kurna lecimy, bo molo w Sopocie widać i statki... Tylko po co?

Eeee rozmyślił się, wraca do PL, nawet podwozie znowu wysunął mimo, że do lotniska to jeszcze ładny kawałek (póki co nie w tą stronę leci w ogóle.) Nad stałym lądem jesteśmy z powrotem na wysokości Portu Północnego. Stąd już blisko i lecimy coraz niżej, ale ciągle całkiem wysoko (900m)

Cabin crew 4 minutes

No to już było 13 minut temu... Lecimy nad centrum Gdańska prosto na GDN w Rębiechowie. Wysokość taka jakby OK też, może tym razem się uda:-) No i się udało, tyle że captain taki mało wylewny był. Życzył udanego pobytu i goodbye...

W sumie nic się nie stało oczywiście. Coś chyba z podwoziem było nie ten teges, ale to moje przypuszczenie. Jak się wpisze Bombardier+podwozie do Google to jest tego trochę (nawet filmy:-))...

url | Thu, 05/09/2019 17:42 | tagi: , ,
Mevo na umbrielu








Umbriel to mój serwer. W pliku crontab są następujące nastawy:

## co 120s
*/2 * * * * /home/tomek/bin/mevo_get.sh
## Codziennie 2:33 po północy
33  2 * * * /home/tomek/bin/mevo_process_yesterday.sh
## Raz w miesiącu 2:43 (musi być po mevo_process_yesterday.sh)
43  3 1 * * /home/tomek/bin/mevo_process_lastmonth.sh

Uruchamiany co 2 minuty mevo_get.sh pobiera (mevo_get_store.pl) ze strony plik locations.js, wyciąga z niego najważniesze dane, które dopisuje do pliku YYYYMMDD_log.csv

Uruchamiany raz dziennie mevo_process_yesterday.sh agreguje (robi to skrypt mevo_yesterday_f.pl) dane z pliku YYYYMMDD_log.csv, które zapisuje do pliku MEVO_DAILY_BIKES.csv.

Zawartość MEVO_DAILY_BIKES.csv jest następująca:

day;bikes;zb;dist.total;ga;gd;sop;tczew;rumia;s10111;s10111d;s10112;s10112d;zstat;sstat;\
gd0p;ga0p;sop0p;tczew0p;rumia0p;gd1p;ga1p;sop1p;tczew1p;rumia1p;slope3;\
slope5;stage2;stage4;stage6;stage8;stage10;stage12;stage14;stage16;stage18;stage20;stage99

gdzie:

bikes -- łączna liczba rowerów dostępnych/wykazanych w ciągu dnia w plikach locations.js;

zb -- łączna liczba rowerów wykazanych, które nie były używane (zero-bikes);

dist.total -- dystans łącznie (liczony po prostej);

ga/gd/sop/tczew/rumia -- dystans łącznie (liczony po prostej dla miast; jeżeli rower przejechał z miasta do miasta to każde miasto dostaje połowę);

s10111/s10112 --przeciętna liczba rowerów na stacjach s10111/s10112 liczona jako $\sum_{i=1}^N r_i / N$ (N -- liczba pobrań pliku locations.js, jeżeli pobrano wszystkie to $24 \times 30 = 720$);

s10111d/s10112d -- przeciętna liczba rowerów na stacjach s10111/s10112 w godzinach 5--23;

zstat -- przeciętny odsetek stacji bez rowerów (zero-stations), liczony jako $\sum_{i=1}^N s_i / (S \times N)$ (N -- liczba pobrań pliku locations.js, $S$ -- liczba stacji w systemie);

sstat -- przeciętny odsetek stacji z maksimum jednym rowerem (single-stations), liczony jako $\sum_{i=1}^N s_i / (S \times N)$;

gd0p/ga0p/sop0p/tczew0p/rumia0p -- przeciętny odsetek stacji bez rowerów (zero-stations) dla miast (gd/ga/sop/tczew/rumia). Liczony jak zstat tylko $S$ -- liczba stacji w danym mieście oczywiście;

gd1p/ga1p/sop1p/tczew1p/rumia1p -- przeciętny odsetek stacji z maksimum jednym rowerem (single-stations) dla miast (gd/ga/sop/tczew/rumia). Liczony jak sstat tylko $S$ to liczba stacji w danym mieście oczywiście a nie ogółem;

slope3/slope5 -- łączny dystans przejechanych odcinków o nachyleniu przeciętnym 3%/5%;

stage2/stage4 itd -- łączny dystans przejechanych odcinków o dlugości 0--2km, 2--4km itd...

Następnie uruchamia skrypt mevo_daily_report.pl, który z pliku MEVO_DAILY_BIKES.csv wyciąga ostatni i przedostatni dzień; kompiluje raport dzienny tj. oblicza podstawowe statystyki, tworzy raport tekstowy (ograniczony do 280 znaków bo Twitter więcej nie potrafi) tworzy bardziej obszerny raport w formacie TeXa, konwertowany później do obrazka (za pomocą XeTeXa/converta) Publikuje na twitterze (twitter_post.py) obrazek i ww raport tekstowy.

Następnie uruchamia skrypt mevo_yesterday_hr_f.pl, który agreguje dane z pliku YYYYMMDD_log.csv w ujęciu godzinowym. Zapisuje wynik do pliku MEVO_STAT_BIKES_HRS_YYYYMM.csv (plik przechowuje zagregowane dane godzinowe dla miesiąca). Ten skrypt niczego nie publikuje na twitterze

Plik MEVO_STAT_BIKES_HRS_YYYYMM.csv ma następującą zawartość:

day;hr;bikes;nzstations;bikesGD;bikesGA;bikesSP;nzsGD;nzsGA;nzsSP

day/hr -- dzień i godzina;

bikes -- przeciętna liczba rowerów na wszystkich stacjach (definiowana jako suma rowerów/suma pomiarów);

nzstations -- przeciętna liczba stacji z minimum jednym rowerem (non-zero stations);

bikesGD/bikesGA/bikesSP -- przeciętna liczba rowerów na stacjach w mieście

nzsGD/nzsGA/nzsSP -- przeciętna liczba stacji z minimum jednym rowerem w mieście

Wykonywany raz w miesiąc mevo_process_lastmonth.sh uruchamia mevo_monthly_report.pl, który agreguje w skali miesiąca dane z pliku MEVO_DAILY_BIKES.csv; kompiluje raport miesięczny tj. oblicza podstawowe statystyki, tworzy raport tekstowy i obrazek (w sposób analogiczny jak raport dzienny) publikuje na Twitterze (twitter_post.py) obrazek i raport tekstowy.

Następnie uruchamia skrypt mevo_stat_bikes_hrs.pl, który konwertuje/łączy MEVO_DAILY_BIKES.csvMEVO_STAT_BIKES_HRS_YYYYMM.csv do pliku MEVO_HRS.csv. Na podstawie danych z pliku MEVO_HRS.csv tworzone są wykresy, do czego wykorzystywany jest R.

Plik MEVO_HRS.csv ma następującą zawartość:

dow;dowNN;hr;bikes;bikesGd;bikesGa;bikesSp;stats;statsGd;statsGa;statsSp;\
pbikes;pbikesGd;pbikesGa;pbikesSp;pstats;pstatsGd;pstatsGa;pstatsSp

gdzie:

dow -- dzień tygodnia (0 -- powszedni; 1 -- święta, soboty i niedziele)

dowNN -- liczba dni powszednich i niepowszednich (w miesiącu)

hr -- godzina

bikes/bikesGd/bikesGa/bikesSp -- przeciętna liczba rowerów na wszystkich stacjach i na stacjach w mieście;

stats/statsGd/statsGa/statsS -- przeciętna liczba stacji z minimum jednym rowerem ogółem i w mieście;

pbikes/pbikesGd/pbikesGa/pbikesSp -- przeciętna % rowerów na stacjach ogółem i w mieście (% średniej dobowej);

pstats/pstatsGd/pstatsGa/pstatsSp -- przeciętny % stacji z minimum jednym rowerem ogółem i w mieście (% średniej dobowej);

Konkretnie zaś uruchamiany jest R ze skryptem mevo_hrly.R, który generuje wykresy do pliku Mevo_hrly_YYYYMM.pdf. Następnie Mevo_hrly_YYYYMM.pdf jest konwertowane (convert) do formatu JPG (Mevo_hrly_YYYYMM-0.jpg, Mevo_hrly_YYYYMM-1.jpgMevo_hrly_YYYYMM-2.jpg).

Publikuje na twitterze (twitter_post.py) Mevo_hrly_YYYYMM-*.jpg

Uruchamia R ze skryptem mevo_daily_bikes.R. Uruchamia R ze skryptem mevo_daily_zstats.R. Skrypty generują wykresy do plików mevo_daily_bikes.pdfmevo_daily_zstats.pdf. Pliku mevo_daily_bikes.pdf/mevo_daily_zstats.pdf są zamieniane na format JPG. Publikuje na twitterze (twitter_post.py) mevo_daily_bikes.jpg/mevo_daily_zstats.jpg.

Reasumując tworzone/wykorzystywane są następujące pliki danych: YYYYMMDD_log.csv (dzienny log dopisywany co 2min); MEVO_DAILY_BIKES.csv (dzienny log aktualizowany co 24h (o 2:33)); MEVO_STAT_BIKES_HRS_YYYYMM.csv (dzienny log godzinowy aktualizowany co 24h (o 2:33)) MEVO_HRS.csv (plik tymczasowy z MEVO_DAILY_BIKES.csv/MEVO_STAT_BIKES_HRS_YYYYMM.csv (raz w m-cu))

Przy okazji się okazało że XeTeX na Debiana 4.9.51-1 (chyba Stretch) w wersji Armel jest epicko spieprzony. Konkretnie nie może znaleźć fontów systemowych, bo szuka jakiś dziwnych obciętych nazw. Przykładowo Iwona-Reg.otf nie znajduje, bo szuka Iwona-Reg.. Dziwaczny błąd. Zrobiłem link ln -s Iwona-Reg. Iwona-Reg.otf i działa bo mi się nie chciało tracić czasu na poprawienie tego lepiej.

Anyway za 4 ostatnie miesiące zbiorcza statystyka wygląda następująco (dystanse w tys km za wyjątkiem Dist/r -- miesięczny średni przebieg roweru w km):

YYMM Days   Dist %Change Dist/r   GD %Change    GA %Change   SOP %Change
------------------------------------------------------------------------
201905 31  569.8  241.1  531.5  359.5  235.6  126.6  267.3   42.9  244.3
201906 30  856.9  150.4  677.4  501.4  139.5  220.5  174.2   76.2  177.7
201907 31  751.4   87.7  570.9  438.8   87.5  187.9   85.2   69.0   90.5
201908 31  781.0  103.9  592.3  466.5  106.3  180.3   96.0   73.3  106.3
------------------------------------------------------------------------

Czyli najlepiej było w Czerwcu, bo jeżdżą wcale nie przyjezdni tylko miejscowi do roboty. Potwierdza to też zmienność tygodniowa (mniej się jeździ w soboty i niedziele). Połowa odcinków ma mniej niż 4km (liczone w linii prostej przypominam). Długość odcinków o nachyleniu 3% jest śladowa (a 5% to już ślad w śladzie). Resztę na wykresach widać...

url | Wed, 04/09/2019 19:05 | tagi: , ,