Monday 27 November 2017

Moving Gjennomsnittet Scala


I helgen bestemte jeg meg for å prøve hånden min på noen Scala og Clojure. Jeg var dyktig med objektorientert programmering, og så var Scala lett å plukke opp som språk, men ønsket å prøve funksjonell programmering. Dette er hvor det ble vanskelig. Jeg kan bare Jeg ser ut til å få hodet mitt til en modus for skrivefunksjoner Som en ekspertfunksjonell programmerer, hvordan nærmer du deg et problem. Gi en liste over verdier og en definert summasjonsperiode, hvordan vil du generere en ny liste over det enkle glidende gjennomsnittet av listen. For eksempel Gitt listeværdiene 2 0, 4 0, 7 0, 6 0, 3 0, 8 0, 12 0, 9 0, 4 0, 1 0 og perioden 4, skal funksjonen returnere 0 0 , 0 0, 0 0, 4 75, 5 0, 6 0, 7 25, 8 0, 8 25, 6 5. Etter å ha brukt en dag med å mulle det over, var det beste jeg kunne komme opp med i Scala dette. Dette er forferdelig ineffektivt, jeg vil mye heller gjøre noe som. Nå kunne det lett gjøres i en imperativ stil, men jeg kan for livet av meg finne ut hvordan man uttrykker det funksjonelt. Interessant problem jeg kan tenke på ma Nye løsninger, med varierende grad av effektivitet Det er ikke nødvendigvis å legge til ting gjentatte ganger, men det er ikke et ytelsesproblem, men la oss anta at det også er nullene i begynnelsen på forhånd, så la oss ikke bekymre oss om å produsere dem. Hvis algoritmen gir Selvfølgelig, fint, hvis ikke, korrigerer vi det senere. Ved å starte med Scala 2 8, vil følgende gi resultatet for n periode ved å bruke glidende for å få et glidende vindu på listen. Likevel, selv om dette er ganske elegant, gjør det ikke ha den beste ytelsen mulig, fordi det ikke utnytter allerede beregnede tillegg. Så, snakk om dem, hvordan kan vi få dem. Vi sier at vi skriver dette. Vi har en liste over summen av hver to par. La oss prøve å bruk dette resultatet til å beregne det bevegelige gjennomsnittet på 4 elementer Formelen ovenfor gjorde følgende beregning. Så hvis vi tar hvert element og legger det til det andre neste elementet, får vi det bevegelige gjennomsnittet for 4 elementer. Vi kan gjøre det slik. Vi kunne deretter beregne det bevegelige gjennomsnittet for 8 elementer og så videre Vel, det er en velkjent algoritme for å beregne ting som følger slikt mønster. Det er mest kjent for bruk på å beregne kraften til et nummer. Det går slik. Så, la s bruke det her. Så , her er logikken Period 0 ugyldig, periode 1 er lik innspillet, periode 2 er glidende vindu av størrelse 2 Hvis større enn det, kan det være jevnt eller merkelig. Hvis det er merkelig, legger vi hvert element til det bevegelige Sumet av neste merkelig - 1 elementer For eksempel, hvis 3, legger vi hvert element til movingSum av de neste 2 elementene. Hvis vi selv beregner movingSum for n 2, legger vi deretter hvert element til ett n 2 trinn etterpå. Med denne definisjonen, Vi kan da gå tilbake til problemet og gjøre dette. Det er en liten ineffektivitet med hensyn til bruken av, men det er O periode, ikke Det kan gjøres mer effektivt med hale rekursiv funksjon Og selvfølgelig definisjonen av glidende I gitt er fryktelig ytelsesmessig, men det vil bli en mye bedre definisjon av det på Scala 2 8 Merk at vi ikke kan lage en effektiv glidemetode på en liste, men vi kan gjøre det på en Iterable. Having sagt alt det, jeg går med den aller første definisjonen, og optimaliserer bare hvis en kritisk bananalyse fastslår dette som en stor sak. For å konkludere, la oss vurdere hvordan jeg gikk om problemet Vi har et bevegelig gjennomsnittlig problem Et glidende gjennomsnitt er summen av et bevegelig vindu på en liste, delt med størrelsen på vinduet. For det første prøver jeg å få et skyvevindu, summere alt på det, og deretter divideres med størrelsen. Det neste problemet var å unngå gjentagelse av allerede beregnede tillegg. I dette tilfellet gikk jeg til det minste mulige tillegget, og prøvde å finne ut hvordan å beregne større summer, gjenbruk av slike resultater. La oss endelig prøve å løse problemet slik du har funnet det, ved å legge til og trekke fra forrige resultat. Å få det første gjennomsnittet er enkelt. Nå lager vi to lister. Først, listen over elementer som skal trekkes ned. Neste, listen over elementer som skal legges til. Vi kan legg til disse to lister ved hjelp av zip Denne metoden vil bare produsere uce så mange elementer som den mindre listen har, noe som unngår at problemet med å trekke seg er større enn nødvendig. Vi avslutter ved å komponere resultatet med en fold. som er svaret som skal returneres Hele funksjonen ser slik ut. Jeg vet Clojure bedre enn Scala, så her går Når jeg skriver dette, er den andre Clojure-oppføringen her viktig, at det egentlig ikke er hva du reiterer og ikke er idiomatisk Clojure Den første algoritmen som kommer til å tenke meg, tar gjentatte ganger det ønskede antall elementer fra sekvensen, det første elementet og gjentakende. Følgende fungerer på en hvilken som helst sekvensvektor eller liste, lat eller ikke, og gir en lat sekvens av gjennomsnitt --- som kan være nyttig hvis du jobber på en liste med ubestemt størrelse. Merk at det tar bryr seg om basissaken ved å implisitt returnere null hvis det ikke er nok elementer i listen til å forbruke. Kjører dette på testdataene dine. Det gir ikke 0 for de første elementene i sekvensen, men det kan lett håndteres noen hva kunstig. Det enkleste av alt er å se mønsteret og være i stand til å huske på en tilgjengelig funksjon som passer til billedpartisjonen, gir en lat visning av deler av en sekvens som vi deretter kan kartlegge. Noen spurte etter en hale rekursiv versjon halen rekursjon vs latskap er litt av en tradeoff Når jobben din bygger opp en liste, så gjør funksjonen halen rekursiv er vanligvis ganske enkelt, og dette er ikke noe unntak --- bare bygge opp listen som et argument til en subfunction Vi vil akkumulere til en vektor i stedet for en liste fordi ellers vil listen bli bygd opp bakover og må reverseres på slutten. Loop er en måte å lage en anonym indre funksjon som for eksempel Scheme s kalt let recur må brukes i Clojure for å eliminere haleanrop er conj en generalisert ulempe som er naturlig for samlingen --- begynnelsen av lister og slutten av vektorer. ansvaret 24. august 09 på 2 58. Jeg har bestemt meg for å legge til denne gamle Q, fordi emnet kom opp igjen og jeg f Det er foretrukket å peke på denne fine samlingen av mulige løsninger, mens du legger til min egen oppgave som er forskjellig fra tidligere versjoner i Clojure, som forklart i A. Kanskje vi kan bygge nettets mest komplette lagringsplass for funksjonelle mov-avg implementeringer - Micha Marczyk Mar 2 10 på 0 20.Her sa delvis punktfri en linje Haskell løsning. First det gjelder haler til listen for å få haler listene, så. Vendrer den og dropper de første p-postene som tar p som 2 her. I tilfelle du Er det ikke kjent med punktpipepunktet, er det operatøren for funksjonell sammensetning, noe som betyr at den passerer utgangen av en funksjon som inngang til en annen, og komponerer dem i en enkelt funksjon gf betyr løp f på en verdi, og send utgangen til g , så fgx er det samme som gfx Generelt fører bruken til en klarere programmeringsstil. Deretter kartlegger funksjonen fraIntegral p sum ta p på listen Så for hver liste i listen tar det de første p-elementene, summerer dem og deler deretter dem ved siden av vi slår bare listen tilbake igjen med omvendt. Dette ser alt mye mer ineffektivt ut enn det er omvendt, ikke fysisk reverserer rekkefølgen til en liste til listen er evaluert, den bare legger den ut på stabelen, gode og lette Haskell-haler også lager ikke alle de separate lister, det refererer bare til forskjellige deler av den opprinnelige listen. Det er fortsatt ikke en god løsning, men det er en linje lang. Her er litt finere, men lengre løsning som bruker mapAccum til å gjøre en glidende subtraksjon og tillegg. Først vi deler opp listen i to deler på p, så. Som den første biten. Sett den andre biten med den opprinnelige listen, dette parrer bare av elementer i rekkefølge fra de to listene. Den opprinnelige listen er åpenbart lengre, men vi mister denne ekstra biten. Nå definerer vi en funksjon for vårt kartAccum ulator mapAccumL er det samme som kartet, men med en ekstra løpestatus akkumulator parameter som går fra forrige kartlegging til den neste når kartet går gjennom listen Vi bruker akkumulatoren som vårt bevegelige gjennomsnitt , og da vår liste er dannet av det elementet som nettopp har forlatt skyvevinduet og elementet som nettopp har skrevet det inn i listen vi bare har glidet, tar vår glidende funksjon det første tallet x bort fra gjennomsnittet og legger til det andre nummeret y pass den nye s sammen og tilbake s divisjonert med p snd sekund bare tar det andre medlemmet av et par tuple, som brukes til å ta den andre retur verdien av mapAccumL, da mapAccumL vil returnere akkumulatoren så vel som kartlagt listen. For de av deg ikke kjent med symbolet, det er applikasjonsoperatøren. Det gjør det egentlig ikke noe, men det har en lav, høyre-assosiativ bindende forrang, så det betyr at du kan legge ut parentesene. Legg merke til LISPers, iefx er det samme som f x. Running ma 4 2 0, 4 0, 7 0, 6 0, 3 0, 8 0, 12 0, 9 0, 40, 1 0 gir 4 75, 50, 0, 7 25, 80, 8 25, 6 5 for begge løsninger. Åh, og du må importere modullisten for å kompilere begge løsninger. Daniel Takk Skrivingskoden er mye enklere enn å forklare det. Du har beskrevet det kjennetegnet av det. To lister Streamer opprettholdes i begge funksjonene og får hodet tatt av under hver iterasjon. En liste Stream tjener som hovedsamlingen til å lure gjennom mens den andre Listestrømmen, som er den samme samlingen, med unntak av perioden mindre Dobler tatt av den, brukes til beregning av det nye glidende gjennomsnittet Walter Chang Aug 24 09 på 17 19.J programmeringsspråket gjør det lettere å flytte gjennomsnitt. Faktisk er det færre tegn i enn i etiketten, flytende gjennomsnitt. For verdiene som er angitt i dette spørsmålet, inkludert navnverdiene her, er det en enkel måte å kode dette på. Vi kan beskrive dette ved å bruke etiketter for komponenter. Eksempler bruker nøyaktig samme program Den eneste forskjellen er bruken av flere navn i den andre formen. Slike navn kan hjelpe lesere som ikke vet J-primærene. La oss se nærmere på hva som foregår i delprogrammet, gjennomsnitt d antyder summasjon og betegner divisjon som det klassiske tegnet. Beregning av en tallytelling av elementer er utført av Det overordnede programmet, da er summen av verdier dividert med verdien av verdier. Resultatet av den gjennomsnittlige beregningen som er skrevet her, inkluderer ikke ledende nuller forventes i det opprinnelige spørsmålet Disse nullene er uten tvil ikke en del av den tiltenkte beregningen. Teknikken som brukes her kalles stilig programmering. Det er stort sett det samme som den punktfrie stilen for funksjonell programmering. Ansatt 26. august kl. 16 ved 16 15. Her ligner Clojure å være et mer funksjonelt språk. Dette er helt hale-rekursivt, btw, og inneholder ledende nuller. Vanligvis legger jeg inn samlingen eller listeparameteren for å gjøre funksjonen enklere å karriere. Men i Clojure. is, så tungvint, pleier jeg vanligvis ender opp med å gjøre dette. I hvilket tilfelle spiller det egentlig ingen rolle hvilken rekkefølge parametrene går. Ansatte 24. august 09 på 4 56. Han Jonathan, jeg er ganske ny til denne funksjonelle programmeringen, kan du vær så snill å forklare meg hvordan er hale-rekursiv Takk James P Aug 24 09 ved 14 38. Rekursjonen skjer på if-setningen, hvor enten alternativet er basert på gjentatt. Dette vil beregne alle parametere først og bare deretter rekursere Svaret vil være et resultat av gjentatt As Resultatet er det samme resultatet som returneres av rekursjonen, uten andre beregninger, dette er rekursiv hale. Daniel C Sobral Aug 24 09 på 15 20.Dette eksempelet bruker stat, siden det er en pragmatisk løsning i dette tilfellet, og en lukking for å skape windowing-middelfunksjonen. Den er fortsatt funksjonell i den forstand at man bruker førstegangsfunksjoner, selv om den ikke er bivirkningfri. De to språkene du nevnte, kjøres på toppen av JVM og dermed begge tillater statlig - ledelse når det er nødvendig. ansvaret 24. august kl. 01. 55. Denne løsningen er i Haskell, som er mer kjent for meg. Ansatt 24. aug 09 kl. 10. 23.Jeg liker bruken av kampoppstillingen, prøvde jeg å gjøre noe lignende, men kunne ikke helt gjør det hele veien der James P Aug 24 09 på 14 39. En kort Clojure-versjon som har fordelen av å være O-listelengde uavhengig av perioden. Dette utnytter det faktum at du kan beregne summen av en rekke tall ved å opprette en kumulativ sum av sekvensen f. eks 1 2 3 4 5 - 0 1 3 6 10 15 og deretter trekke de to tallene med en forskyvning lik din periode. Etter sent på festen, og ny til funksjonell programmering, kom jeg også til denne løsningen med en indre funksjon. Jeg vedtok ideen om å Del hele listen med perioden i forveien. Da genererer jeg summen som skal begynne med for de første elementene. Og jeg genererer de første, ugyldige elementene 0 0, 0 0. Deretter trekker jeg rekursivt den første og legger til den siste verdien Til slutt lister jeg hele greia. ansvaret 29. april kl. 19 på 19. 28. I Haskell pseudokode. Nå skal man virkelig abstrahere de 4 out. answered 23. juli klokken 13 45. Nøkkelen er halerfunksjonen, som kartlegger en liste på en liste over kopier av den opprinnelige listen, med egenskapen som n-telen av resultatet mangler de første n-1 elementene. Vi bruker fmap avg ta n til resultatet, som betyr at vi tar n-lengde prefiks fra dellisten og beregner dens avg Hvis lengden på listen vi er avg ing ikke er n, da beregner vi ikke gjennomsnittet siden det er udefinert. I så fall returnerer vi ingenting. Hvis det er, gjør vi det og slår det inn. Endelig kjører vi catMaybes på resultatet av fmap avg ta n, for å kvitte seg med kanskje type. answered 21 okt 13 på 1 29.Jeg var overrasket og skuffet over resultatet av det som syntes meg de mest idiomatiske Clojure-løsningene, JamesCunningham s lazy-seq solutions. So her sa kombinasjon av James løsning med s ide om å tilpasse rask - eksponering til flyttende summer. Rediger denne en-basert på mikera s løsning - er enda raskere. svaret 22. juli kl. 13 på 19 21. Din Answer.2017 Stack Exchange, Inc. Inngjort i Spark 1 4, forbedret Spark Window-funksjoner uttrykkskraften til Spark DataFrames og Spark SQL Med vindufunksjoner kan du enkelt beregne et glidende gjennomsnitt eller kumulativ sum eller referanse en verdi i en tidligere rad av et bord Vinduefunksjoner lar deg gjøre mange vanlige beregninger med DataFrames, uten å måtte ty til RDD-manipulering. Generelle, UDFer sammenlignet med Window-funksjoner. Vindufunksjoner er komplementære til eksisterende DataFrame-operasjonsaggregater, som sum og avg og UDFs. For å se gjennom aggregater beregne ett resultat, en sum eller gjennomsnitt for hver gruppe av rader, mens UDFer beregner ett resultat for hver rad basert på bare data i den raden. I kontrast beregner vindusfunksjoner ett resultat for hver rad basert på et vindu med rader. For eksempel, I et glidende gjennomsnitt beregner du for hver rad gjennomsnittet av radene som omgir den nåværende raden, dette kan gjøres med vindufunksjoner. Gjennomgang av gjennomsnittlig eksempel. La oss dykke rett inn i m oving gjennomsnittlig eksempel I dette eksempeldatasettet er det to kunder som har brukt ulike mengder penger hver dag. Bygg kunden DataFrame Alle eksempler er skrevet i Scala med Spark 1 6 1, men det samme kan gjøres i Python eller SQL. val kunder 2016-05-01, 50 00. Alice, 2016-05-03, 45 00. Alice , 2016-05-04, 55 00. Bob, 2016-05-01, 25 00.Window-funksjon og Window Spec-definisjon. Som vist i eksempelet ovenfor, er det to deler for å bruke en vindusfunksjon 1 som angir vindufunksjonen, som f. eks. avg i eksemplet, og 2 angir vinduspesifikasjonen eller wSpec1 i eksemplet For 1, kan du finne en fullstendig liste over vindusfunksjonene her. Du kan bruke funksjoner som er oppført under Aggregate Functions og Window Functions. For 2 angir et vindu spec, det er tre komponenter partisjon av, rekkefølge av og frame. Partisjon ved definerer hvordan dataene er gruppert i eksempelet ovenfor, det var av kunden Du må spesifisere en rimelig gruppering fordi alle data i en gruppe vil bli samlet inn til samme maskin Ideelt har DataFrame allerede blitt delt opp av ønsket gruppering. Bestiller av definerer hvordan rader bestilles i en gruppe i eksempelet ovenfor, det var etter dato. Ramme definerer grensene til vinduet med hensyn til den nåværende raden i eksemplet ovenfor, vinduet varierte mellom forrige rad og neste ro. Cumulative Sum. Neste, la oss beregne den kumulative summen av beløpet brukt per kunde. Vinduespekter rammen varierer fra begynnelsen til den nåværende raden 0.val wSpec2 0. Lag en ny kolonne som beregner summen over den definerte vindusrammen. Gjennomsnitt Enkel glidende gjennomsnitt. Gjennomsnitt Enkel glidende gjennomsnitt Du oppfordres til å løse denne oppgaven i henhold til oppgavebeskrivelsen, ved hjelp av hvilket som helst språk du kan kjenne til det enkle glidende gjennomsnittet av en serie av tall. Opprett en tilstandsfunksjonsklasseseksempel som tar en periode og returnerer en rutine som tar et tall som argument og returnerer et enkelt bevegelig gjennomsnittspunkt for sine argumenter så langt. Et enkelt glidende gjennomsnitt er en metode for å beregne et gjennomsnitt av en strøm av tall ved å bare gjennomsnittsføre de siste P-tallene fra strømmen, hvor P er kjent som perioden. Det kan implementeres ved å kalle en initialiseringsrutine med P som sin argument, IP, som da skal returnere en rutine som når de kalles med individuelle, etterfølgende medlemmer av en strøm av tall, beregner gjennomsnittet av opp til, den siste P av dem, kan kalle dette SMA. Ordet s tateful i oppgavebeskrivelsen refererer til behovet for SMA å huske visse opplysninger mellom samtaler til den. Perioden, P. An bestilt beholder med minst de siste P-numrene fra hver enkelt av sine individuelle samtaler. Statlig betyr også at etterfølgende anrop til jeg , initialisereren, skal returnere separate rutiner som ikke deler lagret tilstand, slik at de kan brukes på to uavhengige datastrømmer. Pseudo-kode for en implementering av SMA er. Denne versjonen bruker en vedvarende kø for å holde de nyeste p-verdiene hver. funksjonen returnert fra init-moving-gjennomsnittet har sin tilstand i et atom som holder en kø-verdi. Denne implementeringen bruker en sirkulær liste for å lagre tallene i vinduet ved begynnelsen av hver iterasjonspeker refererer til listecellen som holder verdien bare i bevegelse ut av vinduet og bli erstattet med den verdiskapende verdien. Bruke en Closure edit. Currently denne sma kan ikke være nok fordi den tildeler et lukning på bunken. Noen rømningsanalyser kan fjerne heapallokeringen. Bruke en struktur edit. This versjon unngår hopen tildeling av lukkingen holde data i stabelen rammen av hovedfunksjonen Samme output. To unngå at flytpunktet tilnærminger holde hoper opp og vokser, kunne koden utføre en periodisk sum på hele sirkulær kø-array. Denne implementeringen produserer to funksjonsobjekter delingstilstand Det er idiomatisk i E for å skille inn input fra utdata lese fra skrive i stedet for å kombinere dem til ett objekt. Strukturen er den samme som implementeringen av Standard Deviation E. Elixir-programmet nedenfor genererer en anonym funksjon med en innebygd periode p, som brukes som perioden for det enkle glidende gjennomsnittet. Kjørfunksjonen leser numerisk inngang og overfører den til den nyopprettede anonyme funksjonen, og deretter kontrollerer resultatet til STDOUT. Utgangen vises under , med gjennomsnittet, etterfulgt av gruppert inngang, danner grunnlaget for hvert bevegelige gjennomsnitt. Ønsker lukninger, men uforanderlige variabler En løsning er da å bruke prosess ses og en enkel melding som passerer basert API. Matrix-språk har rutiner for å beregne glidningsavstandene for en gitt sekvens av elementer. Det er mindre effektivt å sløyfe som i de følgende kommandoene. Kontinuerlig ber om en inngang I som legges til slutten av en liste L1 L1 kan bli funnet ved å trykke på 2ND 1, og gjennomsnitt kan bli funnet i Liste OPS. Trykk ON for å avslutte programmet. Funksjon som returnerer en liste som inneholder gjennomsnittlig data for det medfølgende argumentet. Program som returnerer en enkel verdi på hver invocation. list er listen i gjennomsnitt p er perioden 5 returnerer den gjennomsnittlige listen. Eksempel 2 Bruke programmet movinav2 i, 5 - Initialisere glidende gjennomsnittlig beregning og definer periode på 5 movinav2 3, xx - nye data i listeværdien 3 , og resultatet blir lagret på variabel x, og vises movinav2 4, xx - ny datavare 4, og det nye resultatet blir lagret på variabel x og vises 4 3 2.Deskriptjon av funksjonen movinavg variabel r - er resultatet den gjennomsnittlige listen som vil bli returnert variabel i - er indeksvariabelen, og det peker til slutten av underlisten listen er gjennomsnittlig variabel z - en hjelperverdi. Funksjonen bruker variabel i for å bestemme hvilke verdier av listen som skal vurderes i neste gjennomsnitt beregning Ved hver iterasjon peker variabel jeg på den siste verdien i listen som skal brukes i gjennomsnittlig beregning. Så vi trenger bare å finne ut hvilken vil være den første verdien i listen. Vi må vanligvis vurdere p-elementer, slik at første elementet vil være det som er indeksert av ip 1 Men i de første iterasjonene vil denne beregningen vanligvis være negativ, så vil følgende ligning unngå negative indekser maks ip 1,1 eller ordne ligningen, maks ip, 0 1 Men antallet av elementene på de første iterasjonene vil også være mindre, den riktige verdien vil være sluttindeks - begynn indeks 1 eller, ordne ligningen, i - max ip, 0 1 1 og deretter, i-max ip, 0 Variabel z holder den vanlige verdi maks ip, 0 så begynnelsesindeksen blir z 1 og numberofelements vil være iz. mid liste, z 1, iz vil returnere listen over verdi som vil være gjennomsnittlig sum vil summen summen iz ri vil gjennomsnittlig dem og lagre resultatet på riktig sted i resultatlisten. fp1 oppretter en delvis søknad i dette tilfelle fikseres andre og tredje parametere.

No comments:

Post a Comment