Są środowiska w których pewne zjawiska występują naturalnie jak i są środowiska gdzie gdzie następuje ich już nie tak naturalne przystosowanie. Np naturę lwa jako króla Dżungli można prędzej zobaczyć w prawdziwej dżungli :
Aniżeli w sztucznie wytworzonej kępie drzew :Inny przykład bliższy życiu informatycznemu - tzw type classes . Mają one nawet swoją stronę na wiki -> https://en.wikipedia.org/wiki/Type_class gdzie ujrzymy przykłady w Haskellu. I to właśnie on (Haskell to on?) jest naturalnym srodowiskiem dla tego zjawiska. Jednocześnie zostało ono sztucznie przystosowane do Scali
Tak to wygląda w Scali :
def min[B >: A](implicit cmp: Ordering[B]): A List(1,2,3,4).min List(1,2,3,4).min(new Ordering[Int] { def compare(a: Int, b: Int) = b compare a })
data Ordering = EQ | LT | GT compare :: Ord a => a -> a -> Ordering
Mając ogromny narzut obiektowy po dekadzie spędzonej z Javą trudno mi było zrozumieć dlaczego w wielu miejscach type classes były nazywane mechanizmem funkcyjnym gdy obiektowy mózg widział w tym zawsze "wzorzec strategię!". Dopiero obcowanie z językiem naprawdę funkcyjnym pozwala uwolnić się z tej obiektowej klatki i widzieć type classes jako coś w kontekście typów danych. W sporze Rzeczowniki vs Czasowniki - Type classes będą ... przymiotnikami.
A teraz Dataframes. Dataframes zostały dodane do Sparka 1.3 i znacznie ułatwiają manipulację danymi. Chociaż można ich używać w Scali (co będziemy robić) to naturalnym środowiskiem dla Dataframes jest (chyba) język R.
Dataframes i R
Tutaj jest fajny opis teoretyczny -> What is a Data FrameBardzo ciekawie są one zobrazowane w kontekście "DataScience" (buzzword detected!) gdzie symbolizują serię pomiarów (rzędy) pewnej ilości czynników (kolumny). I na przykład można sobie zrobić pomiar tego jakie jest zainteresowanie warsztatem w zależności od tego co tam było :
Nazwa | Tematyka | Czy była pizza | Szybkośc Wifi | W ubikacji był papier |
Normalne Dataframe
W trakcie eksperymentów okazało się, że trzeba odróżnić trochę dataframe w czystym R od dataframe w SparkowymR. I za chwile to zrobimy ale od początku.
Pierwsze prawo nauk inzynieryjskich - "Włączone do kontaktu działa lepiej" W R taka składnia c(> column1 <- c(1,2,3,7,8,9) > column1 [1] 1 2 3 7 8 9
I gdy takich kolumn mamy np trzy
> column2 <- c("a","b","c","x","y","z") > column3 <- c(T,T,T,F,F,T) > df <- data.frame(column1,column2,column3) > df column1 column2 column3 1 1 a TRUE 2 2 b TRUE 3 3 c TRUE 4 7 x FALSE 5 8 y FALSE 6 9 z TRUE
To mamy naszego pierwszego DataFrame (kogo czego : datafrejma). I jako prawdziwi naukowcy możemy sobie pobadać co tam jest czy to w kolumnie
> df["column1"] column1 1 1 2 2 3 3 4 7 5 8 6 9
Czy w wierszu
> df[2,] column1 column2 column3 2 2 b TRUE
Na koniec kilka ciekawych konstrukcji badawczych
> df$column2 [1] a b c x y z > df[c("column1","column3")] column1 column3 1 1 TRUE 2 2 TRUE 3 3 TRUE 4 7 FALSE 5 8 FALSE 6 9 TRUE > df[c(1,3,5),] column1 column2 column3 1 1 a TRUE 3 3 c TRUE 5 8 y FALSE
I jedna ciekawa konstrukcja, która będzie wracała do nas raz za razem a może wydawać się trochę "dzika" w kontekście "ukrywania wszystkiego w obiekcie" bo tutaj niejako wyszczepiamy ciało obce
> filter <- df$column3==T > df[filter,] column1 column2 column3 1 1 a TRUE 2 2 b TRUE 3 3 c TRUE 6 9 z TRUE > df[df$column1 > 5,] column1 column2 column3 4 7 x FALSE 5 8 y FALSE 6 9 z TRUE
I tak sobie działamy, i tka sobie robimy i niby to jest odpalone w Sparku i wchodzimy do SparkUI i tam nic nie ma - bo tak naprawdę to tak jak Gmoch na razie rysujemy sobie sytuacje na tablicy. Dalej będziemy działać na wbudowanym zbiorze reprezentującym drogie samochody i Fiata 128.
SparkR Dataframe
Najpierw przechodzimy ze świata czystego R do SparkR.> sparkCars <-createDataFrame(sqlContext,mtcars) > sparkCars DataFrame[mpg:double, cyl:double, disp:double, hp:double, drat:double, wt:double, qsec:double, vs:double, am:double, gear:double, carb:double]
I już jest trochę inaczej bo Dataframe nie wyświetlił nam zawartości a jedynie listę kolumn. Datafrejm datafrejmowi nie równy.
Trzeba to zrobić tak :
> showDF(sparkCars) +----+---+-----+-----+----+-----+-----+---+---+----+----+ | mpg|cyl| disp| hp|drat| wt| qsec| vs| am|gear|carb| +----+---+-----+-----+----+-----+-----+---+---+----+----+ |21.0|6.0|160.0|110.0| 3.9| 2.62|16.46|0.0|1.0| 4.0| 4.0| |21.0|6.0|160.0|110.0| 3.9|2.875|17.02|0.0|1.0| 4.0| 4.0| |22.8|4.0|108.0| 93.0|3.85| 2.32|18.61|1.0|1.0| 4.0| 1.0| |21.4|6.0|258.0|110.0|3.08|3.215|19.44|1.0|0.0| 3.0| 1.0| |18.7|8.0|360.0|175.0|3.15| 3.44|17.02|0.0|0.0| 3.0| 2.0| |18.1|6.0|225.0|105.0|2.76| 3.46|20.22|1.0|0.0| 3.0| 1.0| |14.3|8.0|360.0|245.0|3.21| 3.57|15.84|0.0|0.0| 3.0| 4.0| |24.4|4.0|146.7| 62.0|3.69| 3.19| 20.0|1.0|0.0| 4.0| 2.0| |22.8|4.0|140.8| 95.0|3.92| 3.15| 22.9|1.0|0.0| 4.0| 2.0| |19.2|6.0|167.6|123.0|3.92| 3.44| 18.3|1.0|0.0| 4.0| 4.0| |17.8|6.0|167.6|123.0|3.92| 3.44| 18.9|1.0|0.0| 4.0| 4.0| |16.4|8.0|275.8|180.0|3.07| 4.07| 17.4|0.0|0.0| 3.0| 3.0| |17.3|8.0|275.8|180.0|3.07| 3.73| 17.6|0.0|0.0| 3.0| 3.0| |15.2|8.0|275.8|180.0|3.07| 3.78| 18.0|0.0|0.0| 3.0| 3.0| |10.4|8.0|472.0|205.0|2.93| 5.25|17.98|0.0|0.0| 3.0| 4.0| |10.4|8.0|460.0|215.0| 3.0|5.424|17.82|0.0|0.0| 3.0| 4.0| |14.7|8.0|440.0|230.0|3.23|5.345|17.42|0.0|0.0| 3.0| 4.0| |32.4|4.0| 78.7| 66.0|4.08| 2.2|19.47|1.0|1.0| 4.0| 1.0| |30.4|4.0| 75.7| 52.0|4.93|1.615|18.52|1.0|1.0| 4.0| 2.0| |33.9|4.0| 71.1| 65.0|4.22|1.835| 19.9|1.0|1.0| 4.0| 1.0| +----+---+-----+-----+----+-----+-----+---+---+----+----+ only showing top 20 rows
Jedna rzecz jest zła - w R nazwy samochodów to nie była kolumna tylko takie specjalne nazwy rzędów i te informacje straciliśmy. Poniżej sposób by to rozwiązac :
> carNames<-rownames(mtcars) > frameWithNames<-cbind(carNames,mtcars) > sparkCars<-createDataFrame(sqlContext,frameWithNames) > showDF(sparkCars) +-------------------+----+---+-----+-----+----+-----+-----+---+---+----+----+ | carNames| mpg|cyl| disp| hp|drat| wt| qsec| vs| am|gear|carb| +-------------------+----+---+-----+-----+----+-----+-----+---+---+----+----+ | Mazda RX4|21.0|6.0|160.0|110.0| 3.9| 2.62|16.46|0.0|1.0| 4.0| 4.0| | Mazda RX4 Wag|21.0|6.0|160.0|110.0| 3.9|2.875|17.02|0.0|1.0| 4.0| 4.0| | Datsun 710|22.8|4.0|108.0| 93.0|3.85| 2.32|18.61|1.0|1.0| 4.0| 1.0| | Hornet 4 Drive|21.4|6.0|258.0|110.0|3.08|3.215|19.44|1.0|0.0| 3.0| 1.0| | Hornet Sportabout|18.7|8.0|360.0|175.0|3.15| 3.44|17.02|0.0|0.0| 3.0| 2.0| | Valiant|18.1|6.0|225.0|105.0|2.76| 3.46|20.22|1.0|0.0| 3.0| 1.0| | Duster 360|14.3|8.0|360.0|245.0|3.21| 3.57|15.84|0.0|0.0| 3.0| 4.0| | Merc 240D|24.4|4.0|146.7| 62.0|3.69| 3.19| 20.0|1.0|0.0| 4.0| 2.0| | Merc 230|22.8|4.0|140.8| 95.0|3.92| 3.15| 22.9|1.0|0.0| 4.0| 2.0| | Merc 280|19.2|6.0|167.6|123.0|3.92| 3.44| 18.3|1.0|0.0| 4.0| 4.0| | Merc 280C|17.8|6.0|167.6|123.0|3.92| 3.44| 18.9|1.0|0.0| 4.0| 4.0| | Merc 450SE|16.4|8.0|275.8|180.0|3.07| 4.07| 17.4|0.0|0.0| 3.0| 3.0| | Merc 450SL|17.3|8.0|275.8|180.0|3.07| 3.73| 17.6|0.0|0.0| 3.0| 3.0| | Merc 450SLC|15.2|8.0|275.8|180.0|3.07| 3.78| 18.0|0.0|0.0| 3.0| 3.0| | Cadillac Fleetwood|10.4|8.0|472.0|205.0|2.93| 5.25|17.98|0.0|0.0| 3.0| 4.0| |Lincoln Continental|10.4|8.0|460.0|215.0| 3.0|5.424|17.82|0.0|0.0| 3.0| 4.0| | Chrysler Imperial|14.7|8.0|440.0|230.0|3.23|5.345|17.42|0.0|0.0| 3.0| 4.0| | Fiat 128|32.4|4.0| 78.7| 66.0|4.08| 2.2|19.47|1.0|1.0| 4.0| 1.0| | Honda Civic|30.4|4.0| 75.7| 52.0|4.93|1.615|18.52|1.0|1.0| 4.0| 2.0| | Toyota Corolla|33.9|4.0| 71.1| 65.0|4.22|1.835| 19.9|1.0|1.0| 4.0| 1.0| +-------------------+----+---+-----+-----+----+-----+-----+---+---+----+----+Czu jest prostszy sposób? Być może jest.
W spark UI pojawiają się już jakieś wpisy i nawet jakieś dedykowane dla R - RRDD
I też niestety rzecz nie zawesoła. RDD to poziom abstrakcji niżej aniżeli Dataframes i to na poziomie RDD mamy monitoring. Jest to pewien generator wyzwań i miejmy nadzieję, że w przyszłych odsłonach pojawi się dedykowany monitoring Dataframe.
Tutaj jest dokumentacja --> https://spark.apache.org/docs/latest/api/R/index.html i można się pobawić.
> take(sparkCars,3) carNames mpg cyl disp hp drat wt qsec vs am gear carb 1 Mazda RX4 21.0 6 160 110 3.90 2.620 16.46 0 1 4 4 2 Mazda RX4 Wag 21.0 6 160 110 3.90 2.875 17.02 0 1 4 4 3 Datsun 710 22.8 4 108 93 3.85 2.320 18.61 1 1 4 1 > head(sparkCars) carNames mpg cyl disp hp drat wt qsec vs am gear carb 1 Mazda RX4 21.0 6 160 110 3.90 2.620 16.46 0 1 4 4 2 Mazda RX4 Wag 21.0 6 160 110 3.90 2.875 17.02 0 1 4 4 3 Datsun 710 22.8 4 108 93 3.85 2.320 18.61 1 1 4 1 4 Hornet 4 Drive 21.4 6 258 110 3.08 3.215 19.44 1 0 3 1 5 Hornet Sportabout 18.7 8 360 175 3.15 3.440 17.02 0 0 3 2 6 Valiant 18.1 6 225 105 2.76 3.460 20.22 1 0 3 1
Najpierw trochę lansu
stacMnieNaOC<-sparkCars[sparkCars$cyl > 6] > showDF(stacMnieNaOC) +-------------------+----+---+-----+-----+----+-----+-----+---+---+----+----+ | carNames| mpg|cyl| disp| hp|drat| wt| qsec| vs| am|gear|carb| +-------------------+----+---+-----+-----+----+-----+-----+---+---+----+----+ | Hornet Sportabout|18.7|8.0|360.0|175.0|3.15| 3.44|17.02|0.0|0.0| 3.0| 2.0| | Duster 360|14.3|8.0|360.0|245.0|3.21| 3.57|15.84|0.0|0.0| 3.0| 4.0| | Merc 450SE|16.4|8.0|275.8|180.0|3.07| 4.07| 17.4|0.0|0.0| 3.0| 3.0| | Merc 450SL|17.3|8.0|275.8|180.0|3.07| 3.73| 17.6|0.0|0.0| 3.0| 3.0| | Merc 450SLC|15.2|8.0|275.8|180.0|3.07| 3.78| 18.0|0.0|0.0| 3.0| 3.0| | Cadillac Fleetwood|10.4|8.0|472.0|205.0|2.93| 5.25|17.98|0.0|0.0| 3.0| 4.0| |Lincoln Continental|10.4|8.0|460.0|215.0| 3.0|5.424|17.82|0.0|0.0| 3.0| 4.0| | Chrysler Imperial|14.7|8.0|440.0|230.0|3.23|5.345|17.42|0.0|0.0| 3.0| 4.0| | Dodge Challenger|15.5|8.0|318.0|150.0|2.76| 3.52|16.87|0.0|0.0| 3.0| 2.0| | AMC Javelin|15.2|8.0|304.0|150.0|3.15|3.435| 17.3|0.0|0.0| 3.0| 2.0| | Camaro Z28|13.3|8.0|350.0|245.0|3.73| 3.84|15.41|0.0|0.0| 3.0| 4.0| | Pontiac Firebird|19.2|8.0|400.0|175.0|3.08|3.845|17.05|0.0|0.0| 3.0| 2.0| | Ford Pantera L|15.8|8.0|351.0|264.0|4.22| 3.17| 14.5|0.0|1.0| 5.0| 4.0| | Maserati Bora|15.0|8.0|301.0|335.0|3.54| 3.57| 14.6|0.0|1.0| 5.0| 8.0|
I średnia po hp
> mhp<-mean(stacMnieNaOC$hp) > mhp Column avg(hp) > showDF(select(stacMnieNaOC,mhp)) +------------------+ | avg(hp)| +------------------+ |209.21428571428572| +------------------+
I jeszcze taka interesująca rzecz związxana pośrednio z dataframe:
Project tungsten ---> https://databricks.com/blog/2015/04/28/project-tungsten-bringing-spark-closer-to-bare-metal.html --- z tego co pamiętam oni chcą zrobić własny wyspecjalizowany mechanizm do zarządzania pamięcią -(haha szach mat cplusplusowcy - ...chyba)
I jeszcze taki patent :
> registerTempTable(sparkCars,"cars") > showDF(sql(sqlContext,"select cyl,AVG(hp) as averageHP FROM cars GROUP BY cyl")) +---+------------------+ |cyl| averageHP| +---+------------------+ |6.0|122.28571428571429| |8.0|209.21428571428572| |4.0| 82.63636363636364| +---+------------------+
I na koniec zapiszmy daframe jako json :
> write.df(sparkCars,"/tmp/cars.json","json")
pawel@maszyna:/tmp$ cat cars.json cat: cars.json: Is a directory pawel@maszyna:/tmp$ ls -al cars.json total 60 drwxrwxr-x 2 pawel pawel 4096 wrz 13 19:10 . drwxrwxrwt 27 root root 36864 wrz 13 19:10 .. -rw-r--r-- 1 pawel pawel 4709 wrz 13 19:10 part-r-00000-4767f3fc-8fc8-412c-8eb7-fd56c25686e0 -rw-rw-r-- 1 pawel pawel 48 wrz 13 19:10 .part-r-00000-4767f3fc-8fc8-412c-8eb7-fd56c25686e0.crc -rw-r--r-- 1 pawel pawel 0 wrz 13 19:10 _SUCCESS -rw-rw-r-- 1 pawel pawel 8 wrz 13 19:10 ._SUCCESS.crc
No trzeba będzie and tym trochę popracować...
Spark Scala Dataframe
/bin/sparks/spark-1.5.0-bin-hadoop2.6$ bin/spark-shell
scala> val frame=sqlContext.read.json("/tmp/cars.json") frame: org.apache.spark.sql.DataFrame = [am: double, carNames: string, carb: double, cyl: double, disp: double, drat: double, gear: double, hp: double, mpg: double, qsec: double, vs: double, wt: double] scala> frame.show() +---+-------------------+----+---+-----+----+----+-----+----+-----+---+-----+ | am| carNames|carb|cyl| disp|drat|gear| hp| mpg| qsec| vs| wt| +---+-------------------+----+---+-----+----+----+-----+----+-----+---+-----+ |1.0| Mazda RX4| 4.0|6.0|160.0| 3.9| 4.0|110.0|21.0|16.46|0.0| 2.62| |1.0| Mazda RX4 Wag| 4.0|6.0|160.0| 3.9| 4.0|110.0|21.0|17.02|0.0|2.875| |1.0| Datsun 710| 1.0|4.0|108.0|3.85| 4.0| 93.0|22.8|18.61|1.0| 2.32| |0.0| Hornet 4 Drive| 1.0|6.0|258.0|3.08| 3.0|110.0|21.4|19.44|1.0|3.215| |0.0| Hornet Sportabout| 2.0|8.0|360.0|3.15| 3.0|175.0|18.7|17.02|0.0| 3.44| |0.0| Valiant| 1.0|6.0|225.0|2.76| 3.0|105.0|18.1|20.22|1.0| 3.46| |0.0| Duster 360| 4.0|8.0|360.0|3.21| 3.0|245.0|14.3|15.84|0.0| 3.57| |0.0| Merc 240D| 2.0|4.0|146.7|3.69| 4.0| 62.0|24.4| 20.0|1.0| 3.19| |0.0| Merc 230| 2.0|4.0|140.8|3.92| 4.0| 95.0|22.8| 22.9|1.0| 3.15| |0.0| Merc 280| 4.0|6.0|167.6|3.92| 4.0|123.0|19.2| 18.3|1.0| 3.44| |0.0| Merc 280C| 4.0|6.0|167.6|3.92| 4.0|123.0|17.8| 18.9|1.0| 3.44| |0.0| Merc 450SE| 3.0|8.0|275.8|3.07| 3.0|180.0|16.4| 17.4|0.0| 4.07| |0.0| Merc 450SL| 3.0|8.0|275.8|3.07| 3.0|180.0|17.3| 17.6|0.0| 3.73| |0.0| Merc 450SLC| 3.0|8.0|275.8|3.07| 3.0|180.0|15.2| 18.0|0.0| 3.78| |0.0| Cadillac Fleetwood| 4.0|8.0|472.0|2.93| 3.0|205.0|10.4|17.98|0.0| 5.25| |0.0|Lincoln Continental| 4.0|8.0|460.0| 3.0| 3.0|215.0|10.4|17.82|0.0|5.424| |0.0| Chrysler Imperial| 4.0|8.0|440.0|3.23| 3.0|230.0|14.7|17.42|0.0|5.345| |1.0| Fiat 128| 1.0|4.0| 78.7|4.08| 4.0| 66.0|32.4|19.47|1.0| 2.2| |1.0| Honda Civic| 2.0|4.0| 75.7|4.93| 4.0| 52.0|30.4|18.52|1.0|1.615| |1.0| Toyota Corolla| 1.0|4.0| 71.1|4.22| 4.0| 65.0|33.9| 19.9|1.0|1.835| +---+-------------------+----+---+-----+----+----+-----+----+-----+---+-----+
Co to za "am"? Nie wiadomo - wywalamy
scala> val cleaned=frame.drop("am") cleaned: org.apache.spark.sql.DataFrame = [carNames: string, carb: double, cyl: double, disp: double, drat: double, gear: double, hp: double, mpg: double, qsec: double, vs: double, wt: double] scala> cleaned.show(2) +-------------+----+---+-----+----+----+-----+----+-----+---+-----+ | carNames|carb|cyl| disp|drat|gear| hp| mpg| qsec| vs| wt| +-------------+----+---+-----+----+----+-----+----+-----+---+-----+ | Mazda RX4| 4.0|6.0|160.0| 3.9| 4.0|110.0|21.0|16.46|0.0| 2.62| |Mazda RX4 Wag| 4.0|6.0|160.0| 3.9| 4.0|110.0|21.0|17.02|0.0|2.875| +-------------+----+---+-----+----+----+-----+----+-----+---+-----+ only showing top 2 rows
I zróbmy podobne ćwiczenie do poprzedniego
scala> cleaned.filter(cleaned("cyl")>6) res2: org.apache.spark.sql.DataFrame = [carNames: string, carb: double, cyl: double, disp: double, drat: double, gear: double, hp: double, mpg: double, qsec: double, vs: double, wt: double] scala> cleaned.filter(cleaned("cyl")>6).show(3) +-----------------+----+---+-----+----+----+-----+----+-----+---+----+ | carNames|carb|cyl| disp|drat|gear| hp| mpg| qsec| vs| wt| +-----------------+----+---+-----+----+----+-----+----+-----+---+----+ |Hornet Sportabout| 2.0|8.0|360.0|3.15| 3.0|175.0|18.7|17.02|0.0|3.44| | Duster 360| 4.0|8.0|360.0|3.21| 3.0|245.0|14.3|15.84|0.0|3.57| | Merc 450SE| 3.0|8.0|275.8|3.07| 3.0|180.0|16.4| 17.4|0.0|4.07| +-----------------+----+---+-----+----+----+-----+----+-----+---+----+ only showing top 3 rows scala> val duzoCylindrow=cleaned.filter(cleaned("cyl")>6) duzoCylindrow: org.apache.spark.sql.DataFrame = [carNames: string, carb: double, cyl: double, disp: double, drat: double, gear: double, hp: double, mpg: double, qsec: double, vs: double, wt: double]
I jedziemy ze średnią
scala> import org.apache.spark.sql.functions.avg import org.apache.spark.sql.functions.avg scala> cleaned.agg(avg(cleaned("hp"))).show() +--------+ | avg(hp)| +--------+ |146.6875| +--------+
Na koniec stwórzmy sobie dataframe "ręcznie" - to bardzo ale to bardzo przydaje się przy testowaniu jak trzeba sobie małe DF pod testy skonstruować.
scala> case class CarRow(name:String,price:Int) scala> val rows=Seq(CarRow("Fiat 128",1000), CarRow("Merc 230",4000)) rows: Seq[CarRow] = List(CarRow(Fiat 128,1000), CarRow(Merc 230,4000)) scala> val smallDF=sqlContext.createDataFrame(rows) smallDF: org.apache.spark.sql.DataFrame = [name: string, price: int] scala> smallDF.show +--------+-----+ | name|price| +--------+-----+ |Fiat 128| 1000| |Merc 230| 4000| +--------+-----+ scala> cleaned.join(smallDF,cleaned("carNames") === smallDF("name") ).show() +--------+----+---+-----+----+----+----+----+-----+---+----+--------+-----+ |carNames|carb|cyl| disp|drat|gear| hp| mpg| qsec| vs| wt| name|price| +--------+----+---+-----+----+----+----+----+-----+---+----+--------+-----+ |Merc 230| 2.0|4.0|140.8|3.92| 4.0|95.0|22.8| 22.9|1.0|3.15|Merc 230| 4000| |Fiat 128| 1.0|4.0| 78.7|4.08| 4.0|66.0|32.4|19.47|1.0| 2.2|Fiat 128| 1000| +--------+----+---+-----+----+----+----+----+-----+---+----+--------+-----+
No czyli dużo ciekawych rzeczy nas czeka
Warsztaty
Za tydzień pierwsze warsztaty ze Sparka --> http://www.meetup.com/Java-User-Group-Lodz/events/225008470/, następnie trochę rzeczy bardziej zaawansowanych i dopiero przechodzimy do dataframów (listopad). Dlaczego tak?
Jestem zdania, że trzeba chociaż trochę poznać bebechy zanim zacznie się skakać po wyższych warstwach abstrakcji. Weźmy na przykład taki Hibernate.
Z perspektywy czasu wiem, że najlepiej poznać i zrozumieć model relacyjny danych. Dobrze zrozumieć OOP i wtedy i dopiero wtedy jak się znajdzie akurat w takiej sytuacji, że z powodów takich a nie innych trzeba jeden model połączyć z drugim to można się pokusić o zastosowanie gotowca jakim jest hibernate.
Z bolesnego doświadczenia wiem, że zazwyczaj jednak Hibernate używa się jako zastępnik zrozumienia modelu relacyjnego co koniec końców bardzo boli.
Bo tak się zachowuje Hibernate na pocżątku projektu gdy mamy dwie tabele i jednego selekta
Także najpierw zrozumiemy jak np. lambdy sa rozsyłane po clustrze aby nie zserialiować w paczce połowy systemu - i takie tam różne ciekawostki.
Plus jest jeszcze fajna strona z darmowymi kursami BigData gdzie pracuje się na przygotowanych obrazach. --> http://bigdatauniversity.com/
Dzięki Paweł za obrazkowe wprowadzenie do tematu DataFrame! Miło się oglą...czytało! Akurat wpasowałem się w moment, aby odświeżyć swoje zapiski w temacie - http://jaceklaskowski.gitbooks.io/mastering-apache-spark/content/spark-sql.html (już nie tak kolorową i jedynie po angielsku, więc wybacz, ale może się choć trochę przyda). Ostatnie zmiany w 1.4 i 1.5 są imponujące - window ops!
OdpowiedzUsuńp.s. Zaplanowałem rozkminkę tematu zmian w SQL w 1.4 i 1.5 na dużo później -- teraz pora przyjrzeć się bliżej klastrowaniu bestii sparkowej.
dzięki za materiały!
Usuńpzdr,