forcats/0000755000176200001440000000000014004341752011713 5ustar liggesusersforcats/NAMESPACE0000644000176200001440000000160714004267727013147 0ustar liggesusers# Generated by roxygen2: do not edit by hand S3method(as_factor,character) S3method(as_factor,factor) S3method(as_factor,logical) S3method(as_factor,numeric) export("%>%") export(as_factor) export(fct_anon) export(fct_c) export(fct_collapse) export(fct_count) export(fct_cross) export(fct_drop) export(fct_expand) export(fct_explicit_na) export(fct_infreq) export(fct_inorder) export(fct_inseq) export(fct_lump) export(fct_lump_lowfreq) export(fct_lump_min) export(fct_lump_n) export(fct_lump_prop) export(fct_match) export(fct_other) export(fct_recode) export(fct_relabel) export(fct_relevel) export(fct_reorder) export(fct_reorder2) export(fct_rev) export(fct_shift) export(fct_shuffle) export(fct_unify) export(fct_unique) export(first2) export(last2) export(lvls_expand) export(lvls_reorder) export(lvls_revalue) export(lvls_union) import(rlang) importFrom(magrittr,"%>%") importFrom(stats,median) forcats/LICENSE0000644000176200001440000000005513764153133012726 0ustar liggesusersYEAR: 2020 COPYRIGHT HOLDER: forcats authors forcats/README.md0000644000176200001440000001021014004267500013162 0ustar liggesusers # forcats [![CRAN status](https://www.r-pkg.org/badges/version/forcats)](https://cran.r-project.org/package=forcats) [![R-CMD-check](https://github.com/tidyverse/forcats/workflows/R-CMD-check/badge.svg)](https://github.com/tidyverse/forcats/actions) [![Codecov test coverage](https://codecov.io/gh/tidyverse/forcats/branch/master/graph/badge.svg)](https://codecov.io/gh/tidyverse/forcats?branch=master) ## Overview R uses **factors** to handle categorical variables, variables that have a fixed and known set of possible values. Factors are also helpful for reordering character vectors to improve display. The goal of the **forcats** package is to provide a suite of tools that solve common problems with factors, including changing the order of levels or the values. Some examples include: - `fct_reorder()`: Reordering a factor by another variable. - `fct_infreq()`: Reordering a factor by the frequency of values. - `fct_relevel()`: Changing the order of a factor by hand. - `fct_lump()`: Collapsing the least/most frequent values of a factor into “other”. You can learn more about each of these in `vignette("forcats")`. If you’re new to factors, the best place to start is the [chapter on factors](https://r4ds.had.co.nz/factors.html) in R for Data Science. ## Installation # The easiest way to get forcats is to install the whole tidyverse: install.packages("tidyverse") # Alternatively, install just forcats: install.packages("forcats") # Or the the development version from GitHub: # install.packages("devtools") devtools::install_github("tidyverse/forcats") ## Cheatsheet ## Getting started forcats is part of the core tidyverse, so you can load it with `library(tidyverse)` or `library(forcats)`. ``` r library(forcats) library(dplyr) library(ggplot2) ``` ``` r starwars %>% filter(!is.na(species)) %>% count(species, sort = TRUE) #> # A tibble: 37 x 2 #> species n #> #> 1 Human 35 #> 2 Droid 6 #> 3 Gungan 3 #> 4 Kaminoan 2 #> 5 Mirialan 2 #> 6 Twi'lek 2 #> 7 Wookiee 2 #> 8 Zabrak 2 #> 9 Aleena 1 #> 10 Besalisk 1 #> # … with 27 more rows ``` ``` r starwars %>% filter(!is.na(species)) %>% mutate(species = fct_lump(species, n = 3)) %>% count(species) #> # A tibble: 4 x 2 #> species n #> * #> 1 Droid 6 #> 2 Gungan 3 #> 3 Human 35 #> 4 Other 39 ``` ``` r ggplot(starwars, aes(x = eye_color)) + geom_bar() + coord_flip() ``` ![](man/figures/README-unordered-plot-1.png) ``` r starwars %>% mutate(eye_color = fct_infreq(eye_color)) %>% ggplot(aes(x = eye_color)) + geom_bar() + coord_flip() ``` ![](man/figures/README-ordered-plot-1.png) ## More resources For a history of factors, I recommend [*stringsAsFactors: An unauthorized biography*](https://simplystatistics.org/2015/07/24/stringsasfactors-an-unauthorized-biography/) by Roger Peng and [*stringsAsFactors = <sigh>*](https://notstatschat.tumblr.com/post/124987394001/stringsasfactors-sigh) by Thomas Lumley. If you want to learn more about other approaches to working with factors and categorical data, I recommend [*Wrangling categorical data in R*](https://peerj.com/preprints/3163/), by Amelia McNamara and Nicholas Horton. ## Getting help If you encounter a clear bug, please file a minimal reproducible example on [github](https://github.com/tidyverse/forcats/issues). For questions and other discussion, please use [community.rstudio.com](https://community.rstudio.com/). ## Code of Conduct Please note that the ‘forcats’ project is released with a [Contributor Code of Conduct](https://forcats.tidyverse.org/CODE_OF_CONDUCT.html). By contributing to this project, you agree to abide by its terms. forcats/data/0000755000176200001440000000000012754676654012652 5ustar liggesusersforcats/data/gss_cat.rda0000644000176200001440000021734112754704400014752 0ustar liggesusersBZh91AY&SYC]@UUᖘt|$}u3`Zh!ҬDCD =Ѡ:( /A{@4^z(TքP R((UU@)G )=t6"ҏLeJkFȨU l-jafiz5+U9R P lҪm()VRI@PڶiZiJkjl f MEbE-: tT֮Sz J=P(Dr !U4-` 0H P( @@l@րʠC=1pQz TE tDJ JEP={ PSѥ*@-͖1b)oVڭ6D%h jdF!fPP` t4l)Z0B: ht:į@yP(PU^ƴ4R (@R"T%J$IP B%PJ Q "Un*zJ(  2" ȑS B!I44)hSmz$2L jx"HBFDz 1P= d4O$DFP2RTH5 4 JHOJyMģ6zdz(zOM6Q*`*~,xu\jOYY6˶M<:$=ٵQ Zv0[dngmT[+,AUā"X0EEYCpGGZQřQY"ZhiIl\یҍ;.lYP82mvutu;muf\DqnۺΫ." ($ig ^Fq}ҕM]e&]Fs}o#x"&o!'F/ ZQ{\^%;xgqZEIEֳ,x}fQ$B" C5/'nxq|cS9yKy7*@*K{GqMsݛgǤNKUIu{";P9٣b'T?ؾAn)Glgk(s`M]ɴGW=(4;(޽39ȔmklZՀR}z>ۛ[7'I8זּݼ#nZÒMDNR'g&BrPFgG/o=[j6B󆦗(0fVv,Wj+$㶰rgBe(m_;K$Jfpᵩv-eg VTT %vD9Fmnt,cg8ɵ mnA%Yt۳AEg)ېZ\LM;mm;Sb:ʒ@\Mc8Mb%.KAE%Id%g}9e>=z`F mNjEf J+`O+a[ce6Bn 5C`d!v̡pƈz!4Yd=qأ]8E19}^!!JVaH*(FjWm9ZrHB 7YekR@i `m \ -i%l(A4;6͍DH\|N"Dͺ\p Ek-d|Ѓ l9`$~y9gr7.6R.&0jy;!}G橐K?r XBجa \λe e.["mXM$k5U%D\XBfc4ZPњ[#4&jBJ 6uT7(SM0 6 @L4+&aQOwN U#KazǤsĦ䷵|cHlwCx#V@ʡeݚZ#("td-lh\HaX`ebEJZфD,8=nY92gl#SVFW4ٷa IW;(D!5&۩`V 5kҐ(hWM, R?}-'«UjCg&% 6 "KQ 8pk5da,i@%T u6&BAT(H]e2ǐ%4K5uP Z ,1&&-pl+7eTE$"ŕo[""֖\R"QiYhlF$ZYeC2U*dh,Et [.ܧ5ȵg4)-l"$6g*yiKj@# v@m1GաkZ@H .¬YK,axlr eBR+hc*.@ Fb0 aU14Jˀ2LYIjlf2ֳyUR2lHmB1ENv,[24P DG \ \՘PD`mͺHUJM&pi-) Xn؀AX^v( YR`pb l*`ZJ*FMD47k͛&ٺ VցJQZ`e3KfaJYmFƐ2DVDš%6ŷmfս⍖)$!TeK#4ARXVDՓDf&HB$,dkS\M\VZ(jH6 :>K"6бc TRrXiHdf`\BsT Ndcf:*]̒~\3ݳ5Z:QVɂ=)Dt4#$!0REn4* ʫv=50TO"KwA?ZH.tolyeiv<Ķ^]IKI'AvU2/ fƵDrM3keFY-Q29aʹ3ɱ%zuvYZu6f3@&[CR@%P8NÂdQehɴ[n8tU~tuge;3#mGwg-:ɷH]ZiIhu'ivg$g[c,.® ˲+6sk.(mNtuGqqgVY6ˡ@$E k1ŒJDu7ؾKZZAG<<"`Gfmk;(Ӕ%bi֖۽\y038۷$n8v$.:; ;G,63;0C~{~7 JC8ﵽ=͵r̉ldvD9eeIfu~kB)2l$eNHC+sJëNmpS? _:$:,ȋkr>D;2K0/6;Gp+*Nˊ(.(K+"̣ ;eev7YvVVaQGgvë We @03Zo4B@Mv1Q6A*%vt/J5&&&ͦu-!Fގ퉅\D9HQ7H"B nĂrXIڼe'w\17` ζ6yblY6ֵk:n賬. Vֳ/v¶ݜ$h6KgE KJňL:볤̢¬8;3(,qgGigZucbmДZJq(Rhs٢:]VUe%YG_^GrF]GvؙYUݝUgM" Ec;(wq6J8mqmҿw4K#! ˨YtTYkn*έq%# ֐KJhӤ8"#K))- TE!iݶ(3328&uiEFd "DgM'jCӽ䄄":-E,gaAKJMm`) 4gYGv;c, *:8m]jˬ*[FEUn#*HC45ҚB'sj*(;s΢Ц4δC-.932λ,.nJ3;;.2(8mٕuEtRZFڇQJm%;+";ˋmVgXT\vGgeqTQf]ewhTdtvYBFƑ)( &Ix:;4!&SPѤiZb t RY\qݘ ;㎴롶TQiQkAK R!B:16h 1)Ji(-҅%i [![(it+TPP%!M!FJhN˺Kӊ&CM-;b@Д&[.(Ӥ4(Z#8ҫ8ŗMChjRhiM FFҔSJRINl PaRM C1mBtMItkk bКMh4 H GM.4HWBRѣKFÎ;P:Ѡ1&٢JSNZ4 (bVJjJ %*]Ev$weehZAl kB M&vZt.44)Hi5we6(;KcJ+H[`u@:Cl)R[`h]:4hMPVg\'YvtEVWhJKl-qQZg\EAFJj FBi(m4KUvuݶ"EhiFq!J JZҚCC*4;#:NZ5@eiPBCkA*E:MIH 4DCC PqfVtutTQ +X+FHRwVQۨ:mZK:4:&TRJBҚ4 RҺJF)CHP!CHe+;+:"B:Sb )ZPJҸH- @:Q҆ր5KM&kK2..HJZѥ)(JiqS:(Ȑi4 uJ$";ά,: ]& VWq\uEƝgf] 4 @4Д@%M t.ЦBКi J44І(hBR Hh!I)HPt4&AAJVҭ+H44%(P&i)CKJJ&i: J @!tK D٤ZECJ @Bƕ(ҭ H+J -](ZFBJit@$+:;wtGXQAJP4PP4P.KKl"u]Zj $@$\?|ЫՅ=+说Aa6x$'=LZYXhh&Yg{Ђ pUo!^kXm(>T\01 `w{ƇNV'D"lpCIDWɑxtHujRnC ̎ӟz>:9)+ӮME>njȼJ '#bK\iOuCAu(Р@ߡH%žsӷ"Jgo zHuqi(u"g٤68Ѓͽun""A _ѡ6~c]d#+.uc(>-b3_2l3eG B!ovY>$~wgw ޜ׼yG!>qyPgH  hU3KoZEa8&Nx ~V(_DE䍏wgvyO9ЪaL컭D$>Y`1nۨzX@UTBh%$]RH:*53YC" T߮V[QYSNEhDwT+8;d9r}jJN"Sy [r'ȳW&(BBԿ>bp; u!(K쉆3obl]ŭi[Ȃ}kG^'8 fj`sP䵣Y}BA HpY B$z[%G XIv.+:؂eC,: "9jܛ\>~za=*q0 t(+P ECT ǯ?$!,+YX ^)Ž- Jck;t'7Jzv.붐$'ɫζ(@PF~ MTA+q xpxpC?g8O'є"H2 /ϻ2G_x@zq);H"|nt=cת3> qf'?K,B(I&vtg4VP7T+o {LVH"I؎\w/hI= ȏB9zޚsjb; C"nnXZ QOYZp0>y&.c\j4NW6ϫ.o?;HBz2i3L\4jQ6.Ω'i܅HGOH}@|b x4@2$V)Ia? *m9qpanLhD"'>l zGYEѣM)[E1q*=&  C,+&?8ut3=ȋKHfޙ`MA)Jm1& sMHB"7@ pu ^ҁ4EMb2~8&RsrD[ !ɭ~lw^W7(|Eb3^@̑"Z=P;M1887>.!zS>)L~eDDu=WJ#0Y'91 5eͼR' ÌBDT(906̈́ZTw]G&,K I} ~`ؒAyx0M}HN.FJ4>+~/~G4$F#46"Owc $FVi9 ɥʫhXoͩqᑉp7;@46 BnǞg=DLNb"[.9qI{ 5Jf!)! @Ӥlbx<.HugZ$^=DY~nt'yi+c_wfK cA;9LCbz*m7` jٚB6$AE/K=Z܀n&]t"O+Y/ P$]!@B3@RFĒ1V8 0D{I=_I,]ASZ3 MeO}om+Ć_ 40=Xo ߾L }XDD&6<=~JNxCh >|`$0GH||x!>Ȉ_K$c?9S)4<1CB$1\ brcHQ?7Q<2ZF-''mCtEY"m_EQQ#Gm_x Dv\ U/EPD_ybs,pƤ@7#_gHI4YRngizvyoqdI-`-OʻTDx_c&q&GC塐I6$:SfgY dbHƔg̕pX jk] . s؈5P #K] \z+ؚ *=xALIW8'ǪX0+VSb*?0Ia-a>{'m?6>;*B$,IڰPՆ^V}~3ZXbFtuieXp@<ҕ ?kŒ"#S ҂Hĩ 檵LxT =LT:^qk39'{)rC~ IJ#ӤLLjR ZO H]l~-~k+69b6Ӊ 3p- s&FHF>o3B`p+SR0$Ռev&iDEYDoG=99c{Yg ײy%I?L\d7̤B8 &j7<))YAuwD֔-wg߸(+L XZE &i]Ͻz^֗+>W$+G p.-a9RX 1,|hA'b| R"Aze 4q!s95߲0P #_9p1e )hQ](3j:4rCllNRee~~WίvYu`$Q$M SV@5EFl"C ";vhcH +n]R[g8tEz4r qpud<qU/zU!KH)RA5_QCk[S([y+hz|`]D쁓Dw&Qq}szҹ}H 6h_opF*U>޵z TLB`3n&Ģsh -n fd#P8!dnRH)=ۍə@xHsy₩oK,Kה4YvRJ #|94Vy`[M+Jl2H,-}QZ0>3,AatǓ 4(Obi!x\>B'PϮ+]83İ6{#3DI٣S&GMzlT)j,S/ reհV#ҩ$aT/i:u}śn!;y\?1"Vq&KFNG&qAC$by"M\~{!Z\ /7a1 :O]czESI^wQ.l磝Ftb0%vA$3)Gk"kd1XR(UiX[Hc]r݈gB\*Vf_3/\nHPAb!Y|zPpq[w$rhŏrYσb_= @gr1n340GVHK'ǔƹыu)Cgf(Yi~NA:F@č#C :H진.`u2F8ZjÊd2$mmX0 a힍S{!;tt@Ǿ= !3_ЈdnN$2J{.L# [LQxo‹1mECU b{!{h} C|ߩbzLx־".zxݾ JbHyl'9Od|dM2)'?gD9EqJ) )kȍeqRyh$i#6_F%xdI d !T?cޒZmwc%=Cm @τ~3ٿXp6"lƟH J۹BC .y^IK<3_}l`C$QOߘ蹌w:6EH+O>iQ=7hTҀ$lkӒ6Q{&D.PK@aWJ5>`L&G=AW Ho8<<%qxS"A!>0}6;629=K2ioϞI}NzDW}~}s?dK$8Ʒဈ䣴ϞMXpB@%$V>|~ ǩ/~ o$lXO׭CGT"e 3v4[4ڮT`v,sSR#\4H odIMpr`E"0]rޑ[@ʹK @O8 4ְ xD !L(FWb?K A AaFFlO x#|5+2.c[R@L}`0F!hLy,~lAM[tD7(R[.rV ~R-%,*\"Co|]8Py6ԬZ&p;OQbaTŊ(W4B6Eal1bBIM VP#>?^*& D;"Hv⨐A h"c1aђ Pz+3>$1<XhC" @dZx}#.ܕ,A{EDb|xcU;y79+3h_ kd +I y7ŢxX5hbJ bh3-L>nYG1Avsk<$Zd#aE-xqP$1]FOo<b@ܮl`;IJQ;H L![$!B!Z|?[ofl)}{^ة5%M] HnvT$2Cq(l0wkbvMk><28jFd`s,iYcEd%Bܸxc.*XkN< zMB3<5%z^1+5+.[+e"FDx+0RK mednׅ%Ē.f>9ݰ *WH 8 i.5ZpVlvH羻9^̾!q =Y58)9i]mB,[ L`eblٲ @b %@DIj}{Z>-UBB+PJVU*4wVh88:"8fJKsu<3izٛ1w =^!`Wz=vL% QƇq7,K W=>纍va^8aE:BFi>xO~WӺ=ǩ{ݷP3 /\&/O |-сԴ'tꈹGwd5˦>ı/n}{*!#AX#;BlJg|Qތ91=/ʴ(B>ä$ҞjLP#gv;D9#Qa #Cupf$KlIA$),40ЌkO BI[.R6 _u"1yQxY-t!UTy+T҃ԇݚ:`w^=>GM+dziqe4ȓ88qdn69J&@4_T+m,e"M)}DQ(;^o[On!/~s)lݣi+gS|z54@SrǠRewoꐣclq Y<i{Oo{s1r @ uwvt |KkAC;;"5Zߟv*z4j|"wYIyt(AHN36 HɛL hL#jDv4ȵeZE~p6d2!܁WH.xOB==N,[ q(H5 cZ̙d| GNCD'.T'0۫0J5I%X3fju 9FWnʩxyEGXZXnCL'E5-H8E9_LwTf F*ޕcFy< Ab:}gPvncx ۛH1=.ؐHdkHk*:Dvf̀R 9mCee !G6.K^GҀyd=["LE9,+2$ѴBG7o(eHߜH6K~6^vO,:޶6StPb6B$x=ฒzVQeg:(ۺ@aV0F,1%ٰ5LhҌYX)$uf[ ݬMm̀a[Y1;6Whiavf0baKQfD\ YHJ4h-r[B*%ݾw7^4u=12cݸzX;S3tZ)ƎxrŠTuo0\.l5qpZ$Im#IXvs}1X\ePUg4昪1v9g33z) Cb}̰uLne݃\Tftp]s*G-B% 90ځ6@]$dGt>[6yKK8R5ņc^)E`Ѩq3h1<Ŗ lNb hɁUx BQ&Vhi3*3N(7d o,0< mV@B@,eD ,V%K(O7-9 R9J#JahW.ӸD:ץ6S4om!Wn](".1> jPa9QBnBq`L`0lH읊ex/Ӈw#hcɷkMma/r3$qD& U0pG8eS~צ7 [ jV"&4 .جAJQIBy;-`l@bsg:v76zEX')ݑ:pwq drKϪ0iԐ) eM" !%Ԡ"uaq+8|"S*0!K7/U}7Yd@񗘲 oLxU 0%+ůFF^,-S"-PAD$^u :U2I!S1ŹkɻY:HNi0!Zs&p,A\ PY S[hK3&33&jźVAbz^60PÖ38ۀԀTT3w 9YrMQ4U1<\x!Y 0F/'F²kB9O]5;𘢣wJb8h@J eȔb5'%-;d4z v3<:V&GHyg 4̼eba~k,$'uxi iI&dy}[]t gFCq.jXat@"$ 1n BXRxNÐf _,c[HPq & ]aǡmR'r%x &4l=\C3oh`K9Cp2+sY{Ί?df`" 6Py~ پlkRgu}XmHS!cTbecq!@'B%82AC+y#K%@usI1qw!& ,-(H\e* &6dڀdiYkeub@&]ikKM$H"!BU fpթC vַV;f=1Xt!TcemmȐR"eE`1d8#X*+lwmD ` Q)B)fXKsmzwyyݧ֛f"@ 1c nܠ- UߕH,].\" j@r+LM%ft6 %2¥l &RhshfZ>_8/֭266ɖ/ٱ])\ 9>Q}.֊4D5#edip !YB\l-e%5nJ $ذ@v$mG`H"]%7eղ2 K)D1hK[vޣAHݖ@!5 kUXYI)!V&v؎2>֓6 (!1,c8Y7hp U#U0 F0^ɣD(EZ"B*R!& .2ji( e`M֚ۈDX9a.n&R& ٔ4dγݝe>YFxi#Y ۔~< X^2&фG0$j>yPL p*O{ ʌ)aYVs7HdI $l%9l]' 2D%ZbI4M GlXB&@1$f罞u"+==+|y"<1d%x{,8|󜐚9+kHKV nօ%Ƴ Ie8$̀S+ "$3]Uj)Fl#!%)"Hm B0k ;qXj[J۔F 4S `+ݔ HSX-exz" |`ӟdm>vtci%4!}l/ڰp9 +Cq!H3zw]Cv; .K o~>l6^=9Kq8;eo J)DsS<8Kpf$I L1%M25t l!r{UtQ &U[њ]7Nk95k Snmi\ϧ4A0>wvsǃ H,+HԊ\J6mNj}' 5ң5y;mT,QLL0̈́2$fY*Hm p(~!.Gݲu\($6%/ D) ILR԰!'-4 rÌH([B8@JJ [zYzټ:tFk` \mLՖ,1 [I@ ru ι;11:ul@ )(#7zZP7—=j<\VE2Hx"R73zHL a%\Fh`T!tGH_G>=(zAٺ$S< i۔ IVܫEm)- %%$LaOzl7'!pmI4:pAP`a0ZX T%(RYW;GJt=NcLB1:(*a#<5äxhF"H37y8Y}Ȕû[b.I "O<,xĉ@60` i&j,"3u' #+ ,!YN{pzvN=;eȥyY-0fDIl+|$a @a.FDlh5@$ctŖϓ! P6y3OWmA==ϥ癃F}qUޝ5W ڃ'ʰȲ5pfNYhYx?_}]30P75uow~A4L6IIDLV#AmͰYJFn7XFDKL qnȱ Zovh.a K֬mF(V! WmM9,KM r aRM015ReP"BWn;q`إm D[la+K-yA==tW)% -len5+mJC )Lk( i3Iuݎĉh$ep&2\W!r'o{{/8Lȕg}<y[ǽe^ Mę5H[qBJc5PH(a 04MI43dm53P8d2S!N{1vkJ@Uݻ͑ٸҶ@k4v0$\@iIerQ$J1QYF))(i[Yqӥ&r8ARC^lleYmB0 aQ"dKӾvR#Fs\JB'L;$BX5eRJR&JJBm$S1f6)%b*;`pRb1-}>lm*td"`I!S.Ȑ!D%3 Ѽ;!( a[F҂A P1 c&$KA.A6R ,slJہk™ۡV"5( 0 [!!+1$!Y/۶DI*+d e0W%R R"I}}>폴Ly}݄yyV n".XM WIEelq#$!HnX$! Rbe0 T.wni "HDϾ|i{e0"ξ]5ݱ[%)M3WDQ -9L* E4n+ҳI4T4JGiM$7mlh𣣩yBR"Ai.R@UKpZa<ɤ4)'smL"HbVbd "H4%%9d˥,r ʔT] Q.0Y)IBDI EP"Y Ѻz7vԐ'7nme|(}O{[I&[R$H0ך$8L @cQXv 5ZDdH#v$4mA  +b8 IIScwmܜwxcKfUM2h4{&dm{yYe-yOomYE|ܻ&6w>e|Ӏmr`d])XSwK42l)n[KXAr8m)2&ZKR602rd+K,4a$۫i,2%! YDRa Ёm&\f@f+L 2ī@ Hݹ(]e vՁun&Ai+k©&b, $434Ҙc KRWLbJe&# m@%&S-aZ"H[jca0"d "hiu$ eif]yyF^y^ېRijDVjJD RD"3ftlܠk em@p$ FUC稺;E}:^,`q0R`H4B 'KXcq.75 KV"ě38 %pV3(7Գ1dj̒5wFx #e"LX)tH^qLbzyizWBe۲~[GF54 Dc%/wC/TVU!-2 kd"nMcStq(o:0HOP[ɒx]Z\@(˕}SjIƗ.: 'lK!Q'NIߚ^̏df"OE3FrHzDۦFpO :0(Y s+R'xB2P {.wSxYB ":Ɯ6тZViAP;q"~3<>ܴŠ@H&' .Z/0j荰F2FA@deFlW TzfmgHR;l[ &3ZゼH%jnzܥaC`+:h`%0Txq.WM)Gs$c/BF#,i2\y@$5/_4UN LMaN1ȆL.0 P|$}7 e !.5WDo$1B)kj ?xٱ4,o0 ȃ9nU96t5F0SZ/dy'fCTp{1C1Y)Wk,sc5:pXi3fTDnb2t!XTu$C7 bHK&w1wZ#1-3(T }}[R=cY!ISW4,i<ã̍mTrNM8$`WDpeEYb'2WZ,qц@Y|B;j^m 8/dхM>G7` )Y؂E"ٍcuTcZ |萄Fows)T wm]۫GӍn1_ϛ: bwkk<6M%{Ĺv\Z/*`=2#iWCdqkdGϏ;o4얎=}0D#Ћh>G*\3 %LE1w䍧.gA_K:~n_1XǎuDVrlbfq0-̲"⢫ |Wٝf0Ktsè|}jvS u4k<j>Yպoy;EeyV^S>՛ξ*Lg{i8ՀPT:*6 oppp=ݬcNg9p37&b CoM"uJZJۧ&ps" l`zc̚YÅ,,ddS$H>wwZ P\LmlhÓU˄!t噇 lqP­3nތ!D:8 Ǧ1C#D-:1$ ?*"4Y:kE705ü'uMESBw:YFŨ> \RI#e+(S!cƉ!t:5C*aG0yC$ݩG dLAI<$ Qi0eab$Bl$R:ܒ7aOM]4u ߅DW|8#F"3rjmm,1؂ő{r^ e:1X\&BRm̮JZGZ21Z^$ ^e! J!bؑJg !Y,fRN@,"9,#F@d5ZBхs d*70@ⱸ^5|Al&JS}wGy#ߴs^9v$PvxX4!OA`2,OC/=7Fn(LsG!iIa>z-iReNNNbVn69 d2cYoRMa5[l~;:ހkߙ1X\T܇{;@VFg dڌwqV&&tZVbi?^EەknBT!a$Y>nўbGŚ#6 "XuŊE%i|xI˻Df&[Dw(өa9c5ydZ`j5w{$p ˙Bc$| ?G~$2 ".G|;ކG\ af`R! 6,HaȜlLeK[-YFmQeD0ph̔]#Vx$0k`a&k.2녋VUl82gJg- (ƞ4V6%qcp6yThl7n8* Mt$a^5 `xQe@Uaz ׾=G}|H"}CQ&g|ptuvZtaD"j>wXK: cn 7FkD#iS.ƚB`1 ȑdaeFK%5#'v bA^੕HvXڐdM̳^K1HjgwyRTг1%r)16ŒڪG35%ągC ,e =7nXFN¼4Bg+& "6pA,[1*;F"[%NbB #(;6:A镭&ѨWIe1Y5.Zh^'*r V%}Lh%ô xQ Z&c.!MNH 율Rzos"%(BIXILVB%'[tFWsyfɌ@ص5iR([*apݘD2 | 4v<7 x Bk%-tDZ )4iI*A@w)tZebFvŭ*kCpL̬816FZ li5fZ@[a%YUU( r9P3mvTyZ#WG0T$Bp„mQ,3Yq'U$pڒP"0Y(lzyLt4Ђ&zT-=S ZhQb )JmC`mq˧^)+"-z6HxQB grwV(NMh$X"XrmPfCE]SȀ  #XI$䂡ɨpׄ]!bfZ!"Kq YX䱼Pp)8ّ0V5brdb1Z/1elk2b LQ6AXf(!4/*l7Ka\8\"  uzFM}m;/$hemw]ƴ$p|Q;Ӊ=zlqw0Ѭ'Y8 Ivm0I?&'NH>P62p{"iWa?C/RgF8&o#O^ lx\=o2ك{LOPYO9xC'ЩЉDB;ݝx&H= x-J%*Dax I3t[&pVAAQR;qYunVI(:Xpcx>iOIqC\Ȼ3M;{T d%an]5S̅adWAA XJ5Ҡ tEdN#Q'"SȈfڨX1ZC {ZXRӔc3|y Ս=K37NʚWrҖЅ<M0©1M0MjhZS>7dbV\G6_qCG\c!m$ ̡~ 3 ^&.Rc NK ?'/^%cٳB3Tw+#JYr|dGKtdTZ̆bPr8RNPqFc.*R,i陁Ƒ4*1ܸMi%JYvHEnGf>Z:p,;IdJɆܯ`^ځY1l8Rk* -+YNb4]b|f3,rCDׄ(,T# HoyD%  c!'Yg}_tnt7$lەL4 ƒ0(MF^NЬ7KzŭN;-"ZmӬ}u.3}w/X01"FDz2rJRR@?mΜ2<=pz`pJ-=>U~u؝Rnm >ea,,4ŁAQ5C0Ғ組c[)9q~ =ⱔH|=I1GsraX}6M)$dϳ\?CbGsfב@lb3[aݹǕId,3@FEbG!UVbHЀ*aݥhQ2nzNe @71SH2xP4Ͻ X`fIhR7tVРQE=C,H,I 7gL"}A8ΉB f. ״6gVfO'ӓ!"B_nRmM01ߟ7gldi 16GeHx@X=/Ia0z"BB(Ȱd/K9X#X{u6贳;*J)IvM'c"I`zbXbD)>88mZ F1PC 8@LN !ݷ ~{~wJUaLHC~V1햘J`Kde夦M- c2ãV!;/"m5,fKk+$߭._K_8+M8 bbbI^>5'3ar_6m}AeGF/ŷ -rKs|߲P${_#k?=12'Je4#*EE+3;R0)DÂѰajN[ni):;$/ib ,HCJ7D5,̶ T۠wBо3j=a=fF{{݄WJ}ݪw}/?b`XDX<E]>,+%JbEL@g͛($6g8Chz3Ƿraioe .wUI? }zXC$@/c+/Ed C"mĿ*A$\Ck=W \d8\,1|HD9 ͼfm-~~Ww\UY[,R}VRx:D$1"UFR3bG= Lhɨ}9($CVɺNCLBK Ԫ mܐͶ#76v[RDU& ʐX .TAb 2U@i_^Ilwm[~$D1@@OZb\Ѡb<آ`00 ÊTBT\a gX߮;?{~6l'K8G-*MS{ד32,'CnKsFD:!OeP>3ʐ&ΔH~ D{P"Xec.l`Wi ncz>0i$N{ggy# =S@֖b}Թzjd$D*]" SR|/+b=;S3\d&L6 ?f}9ʭ_hY` T6\ PE'ƌ0a` S@=6eکU zRQ.|hd զrN Ol4Q\)>;+@!el%!Desmv|UH+a((-Lgdц=>xB/nܼM-P6Y-PL!\8lm0AsZڟ{ߧƳi]6[igX`zYKdtP#a HƸ-ͅ N[8nD͇s-NNz އ?UĚLdbV`] ȕ*$צb}|_ g9A eP;a @Hdz@؛#@XYnFszsONjr;B"#2OgЎ\x}^Law(ͯ0 @vרqdTnԉo4"Ǖb{Hz|Tv2! ŅU`J&S)~-a,!,J8 &Q!8~mbLZRR=HBt~1FxOV" ,JhD٢݀dX"8oV㊣o*ӔH;q" ^ȀFn0B B@dyt+~"6Qj5I C>|DL( CH `K }>$.Jh-)~o3ؒW'.Xd ~ϓyv[7gDIՆ#!)Mϛj>~q9V?وFg˙J1+.`>Yj+:tɵR(!Tjc+b@A=@4mB0Ȯ*d3'ٔ [ha)x[b qAK֗,XF ;+.K/~L"Cl B=3yS#4'蔘9Rq/]6BESmGJzv_tZ2$9wAV*I \XF*%4xd$3r0V*T^r0^2QפM$ճa"$I@!/S`F&b,^IܒՑ P&`bڳ;M2^݋6bӳm_]Yzv0 %$E~M{rk0bI|e da%77be$F :4ٟѧƟey?l(ԋ:z\T`.͊@D5.Þ=3I369X:?p! "?B{--}NNH>maP`hGH> t].;[q)R0Ŏ,ֲoSk[XAޫyhXdbe B&@![%ch Ŷ[=|aqFN2;B-sJlr9[[%Z#G@3Y$ F,EX $g0 5ljH8cQi ()!%Ok)ARRg|xjIIL@B,V@U?Ktm'M12Pݥ5V8]tm=o,I4 >`OqYP>|V(Cd[>500>)*V ,Vpk x!%# ?dqF(яHX5dpҁm&= H~7޿{h8N/ܑQc`bH1$ʡ("FBWkj <1$4 (*ݹDu4<3>W6-N )/$F0R d/8~̜H:q$Xyl H2D²&C{?d\'[8Fl5OlH{݀]FdLG0Q9NEH~)խ2QD`0;X!Hn2i +3oS h{X<#/(U  `,apH t,*1Z.YI f!>2Ɥ\3 '-Đ'Jbd ?DtZ ..԰bĔ%u%Y@/bmiqewNB@LΙ9m F}9Ôfd! ?2iT>;ANm4(,K%I;#d=Bp4GY B lbrӼȮkXv|y:p(Hu9w("(b$DіudWFpvଊmfGdW Hc 6 l!v0T01"+0$53)JJHgdӿx@ܼ͟fRiM$5zY$!")s' bܰ }5O^2, ZdCXBEaJI~z̔6v䤤xL_GYHn*,mtǭYl 2j"&#mā<=X{9\VJFyۺ$j Mvۑ&$W# L OזtTo󽶄k1C6L@2G*BAB0~͔=Ь罳pLM# |e2R",pqgfg[s9__N+Y4IX`dX#wd۶YZf`5uQ'y [^PbW󼼻(+,/i(8Nl+Kn~52좞՗E:ױQqu5ӣC贸:Ή'M$A022<>kR% `;{ 4=Oːwr=b^Z ZEi^BVeI)0c&+8f7Y2bL4$ri9:[ׂu6ɧl=a !TF)O)Ihh)th5Cմ2Eq2$q'fD3܇y=MjxIC샐3 B[wu_YΊ(8y^۬ }kBh(t$UYM8mז]WVʓih(hO픵2J@τ89z"@$%blMo]TqAkl #h`wnv[o;_ + ` y:,χ4;JƯ`u4>6$CX٦BEok }kaz#.&D(:1I*\r'pvX$)2xʦ1 Ab`xZpC/?{F(WK>1 z>kyr}5ʼnaK Ͻ7 0310yzۖqvIQ~\wNҐ:dod,A o^>Jl:HqH=) coX5Ltfa2"I,PW 4G-Aݞ룅' 0$0 ؙNMڅdAKG&rc@ha޷ ~}n|ӥ*Ei2  NG݌yfeYg RʇR9FB預i ,RCԅ^QG&Tu6īQC7ME 1tRH 7j@6$4Cg;8`gݞu#>6l,QW}Nqv%ځ 얁ܱ,#Ss4=n6A$ls(Ne\FppI>{#?OL0@HKъUG׶l:wi]Գ;cf9p()v* slfjE)F#!p( NMhsu&rq͈(FՙU.D. wL𾖴CT&y߷pIH+S{oVCODdjOHg~_Mjo^0 !=kgӚ{n}aD fXCGl̆V[I!#/7aKfV˴hQu=nt]m0F!Ӳ4&@nex ^5Ϫ# 2MJ$ %$$Ik*mTall*t x!(τu,X@C ='t&x g-\M ␦MTG4ݤ-jVB3L4AK.~F8-ăbL@Y(Mg "/(d> %`N9_9A&=)b~Y9; (PsD DpB;)K6Xg6flVLKIH/>#5eEk"dلD6aB%:"F$7 !ZB c40{2I&B I3,Q#ţ1B& /)GJ'O8X'_/6= 6z[4MߍJt9 jt@A $T~aVJY#iXU8#>&(fX "$'D>YXXoc8ӵCO`Bɴ $V0䮦Y;VdJCd6l##:ŬHW5rdHAf޲np<>;pbJfs$@ {,vTֺfqAڼ.]x{>_ $IR 7̓$,4id)$dH{M^$酢=+)2XN[$AdfGK@tgX!= b]q)jh@ Xac63İNi[vґ2 1"Q˄eծFD˴5 0Z"K{m863 jg- LKёrpk;ٞ y )so4ߌxHù% 21]P =06"p IJw,ڢpJatjW0=d˘dJI%Ȓ/+IBS~ters}r6cd,\]h'6?OS-'Ӊf0 ,\#8O!8>H۳}pv}&] + ZWZ}{)gW[T$C`|?f gWϮ &28LX@ca @AH4A|yIHn gH !샱W-Zd3xɶe k(NCizpO&* 'I@ӛJ²9#*[p-5cAtum@:lIƚo>9ҩ@'P$iC|,6ȁS}x3 8qɕ *b.c$;6}!*,n`a)VS)ǥ9UΌH9+Y]nfa AtY#W&vIcNh1y 78CӲ8aS]e`2qt? oT=b qtD(K: K?V#g t ͦiA,qp^/P%-`/Wd;j,J hyV:hmaސ%6C܈?|QU?- ?+?}?v8!~Y6Q[c܁PNA$G$a 1@? (!%ou|E_?oGI!&G(/q%b<\6V E+#k+fOu`✔lQ`P `aa$p+/DkPM9m29ex'{~q{+Rqp%vM#yQ'IzL(c9+ԊֳdN{zO 47]/T%)mS>{tn+9 c:OmU$38BhÃ?x  /yz1]ȑ/i)N*T A P~X˷_ԑ{; r?ſn[sU9~?~ڿ3{ T/iOwWd 8a2so2"H4I9't ^ 7SXX]tTڱ v\GjE و۬rJ>3@[V~C~YGRhs9lˁ 13b-$oXZCwoh/)(v=37mj`҉?Xo&5V)J(y.%]fLDg }M8b0"Y_ބj=jYVM hPQUڲ\AAyX72'&x,t +bһTA$O8aң?=_|G0~_^'0 ,y[WsF  @Ն~Q#QUDtOS2:9ym[gTɷG޳P&70%~Dm)E7'w#09A G?WJф-;~8 @Kpy?#c 1ӳڬ?Yy *Boqv KtZT{7Rj+vEx҄cW&9q94C ??_;Z=E=}~bށ$ ?  P_m`o㘎3"V* \jBڀ "ͨݐK[7qcEA3|0YF=i?E?q]~0nNV={QoCjm 2N 2CE\/bX%lAT,N _&/۴O*JF[P$4} GTIteD3& GgܸWh*$(Ѩ#H@3Aj3?t@,@oۈo>p礩 Gh 7 N+s~cϼiȣĔzH|`.#CR]2u`,F/ノVԽkKL 2h!,Muz/b9J[Y3gm#?{:)DhځUY#$^=G(V-UUWuXܡ m|a\ ԁ+g,(_Cumqx@D(nqȊDCX/҃c5wSi/R|J}qH0@C# Dp\O?X)82 m _jx2kPrIm|&q1&l?gd~_o_h} nZҔ 9Lg6r<裈6Oeqf/GCi O3w~6U _Bh"|ݙ#sl{\S|De j4¹B-a4 u܌K~:He~g}7VP.8-Ow&9go7xjʘyDTOJ!_pnIkhY|hy-$u4xkt/=P/P)$S-d]Q%\$~,kNa,#q,q?/hW vI/K%qذJ܀Ϝa)RhC_)86눡\I3.%0_F@Y;Orq=#|vI^8_N0%!__j|T}Aяc ]quZM!Az\&zQ0P@SB?,?pJf?`cx'Tn*bZAP A@ׇ0.㛪 _!uAch9~k_RI;_?g7>K 2C~H?e/4"1h2M:YSZ/$Qjtnh/ N( 6$U>9Fͺ"tUng-eWUTr6S{(DQw+?Qq?2!m3jߺLQj. ‘CࠂM$"9qs:GP\{T -D?d3K,^MAbbDɢX鑢4/f4'N+5طr"?XU N2qpܲv:3t} [>a]P^n郹P:F"AKډ·w949b;xl`%olQp1|f֏Z8TN>IHC5>SLr nW#E(Q뇾IgUM}m7Z\'?Ma$-$N8ƃGOt. ^M:҆f>~Twޑo 329Iw^)qESl`UArPp,HQ?*;_w;2X@=߱S@l)wYuOHS̷RQC$hRF ֮DX |x*y yK{DȥlңʁQ~SDY;ƤMjmuQr} ԳaJˢu4(jVʿO[J> ?9}} l _0 V4J#-$,@~!˜,A| A4Aaq8C Ta":wD<J]Y8`p N0 * (h 8O Z-( XPK7Da?!+s~enO=C-J8k h? ?G=g0 U`eWta鋤#역A6"@Dir^zXY &?mQ۪ hM+-=i}+_.5 ;)l.D&M_:W 8?Ȯv$;PNc0o@m@0P_Ύ>#{ލ 8#" a$C@p_IA_{$>AB+_g`Mp:BWq,"AY [1}kA|jLQ}sE?>ߵ#LyOIg5o'Ty37*?WvC~Is7bj.A?~9$/+ʝ;8-{"QH$ LcyjKaGM-00mD{3#m&i{PħyLO:Sf9FE؛$S̱\3 w=@@$ +&Mdqt?ErIFiA..C64U86P18$$%2L R}J7Q:U ꃿ~x7nwc\۔3X(aWJn]/f1c! F? CBݙF\uxpbyllҀTwV6mhZHtAjpJ7@r*Μ1f̏kT#;gt7eD @,0{a ۼ@jx #fDwlh== ϲP2S>ld2&Q0?!VM$}]%'k,F"LjY0.B" DžDmr}0 cQڒ܌7 l\!n/I̲ \k P;|?EE+1 (f<9Ң7 !rDh G~Cs0Q^j<熈6 Q@?TeaNMxGXz6( Cm {2lͫ/( pM{Bp1D~fK& \{O/w7i)׶y= yc"Pai|ӍI C!td (^Oէlٵ$"1Q蕄VX3aX@4% b.l;OIcM~G? m[=W?&0nG S4r}x\9$^ՙf*bc;(#"Hexade#9k+vFSw 7zI1$ID#H|BX2 4 VM'i[9W?~G|/c~Bڢ :"/ Qw73D~c},J؅eʃsbG%h!i?sO{q6lJvhNlDKʿWp$2iVbhA9+J ~Ūyy._!*CB_a5Ķ!u_ ˷E  <12ۙl +U{µ?XD~Q;LVO'm7ѷ܊|.rP@AEy/~#0Gv' ^QzLڒ P~q9$} ?^˪rcL3)D߁`U?Sc`1M)oboZ)0*PnUx76eGZ"^_)k)%t$u ҄3)aIY ,,3S' d>[C6٧x۰l &t 8L~BR?y:7MvH$)\D h;"hn6=ϹPCͰl ~U1깙pG=ޢ\iT*6Ӳ \6O6K0a`lOP c4z>4{Y&h?i#)`Oe/]e@h|խk`ѹr{wפ͆zN8"E" D}ϡ޺W3'V r+J=̜*EGalCKꆍD =|Nf֙I|Ek1\gWGo'T0lٶ͡!g lai#DZ?wl´IO>\(6("={J~lQ_]C=y.9H+)wcw b/m&.`$}N#!^JhѾ=W$\2XtMtJ#g4$ '>ׇ`ͼ0Dwen((1sE,Ꝼ4bO.;#!C"y^O|xѶ]J8iS5V, PĊ$nٶ=T:fs-9-#\fxgVN ̕ `*bj=͇Fc/qԟ2z;mN"(c(Z6BvN~R"EgwEsRbđ28CF/64j#޽ֈA={oZ |@n"2:3b/t#>`<ɰFܳob4Rl P_M`IA#$[h|2lM&IryB@S<b*C1t~<,EU~{y=Gh3Go,zHIi6D셦xOW'1?|^)'o?^> L_[DHhF$c4Ec>pHdx5ڰ@A"G Ɉ^n"ۋ("!J]d 4Fh'y_W@mdͭ}XH~mNa6@r&2@sal9vDI3q ! o֒ } wf|VdBQO;|F @"/ a>AѱѰoCOidWyrOlbD <9>;Px$1yJr燓c6$ɳQ?=0vQ1=MZMfѳ"Gb͇lɥ`Ř6-D+6p@0/ 4Epv@ď|7Fۗ~8qkIum&^.HvE!l MOj2F?8L?vIIp@O鷆23@ 4g>3''|dۚNI?u>3xp "n0'MB0E:>, I q-˅kxw܋{bH$`/֤3l0y"@Eڍ-{87hX<`Z'bC"0[H rphh ?Rb 7ϓ wxϯ\}לW #rTE $xhdbPA$<{lqʷ~HC$qBZ/"$D8V+l8aM׬{:V#kw"r,;$(}%BkZm>&MyǺ_XNA5C8u|9/R ʰ桒-sllH"Z0' qucudE;bJ 3or$I; ;^+ i"#aN߄=`Ȳ0x;jALP A?_<_jyb7~mo_=M)g?䇑C|lGT-yL,OM$N<1 Xf/p7|u"J]ZwT߬&b ¥a^q[ڄτchih(S{}Qnc"(FontZw?$Z#Sr8Y !"m7?𸑽 RTN?~8oƩ4 قVw3 0]3Wa5l}AU_WrC:/nIӪ6MŽ4LB|VSgnfOMy\u^x$if4qCߌu1]P#w )ZCHމ֪P oz+&kvؘrWxN*on^vbPnyLe?zi9',z~<.eN2\| O i2Ǎ_qn %V1zW@n;?2Xoexu†%8/8nj-ЖxI?BZjЀ F&@n ,"4PTrTE`YJϮ T$Y?Kߠ.џӬ.&EMc"&8@|aD.0S}SO_7J˷k.ϡG_W@OT9NKwq7;b%-S84YRaUh#; iq_f:zOCr>7#$Ǵ; ]>Ʌd @yhպh|$*C3 'E z0ϛ_Юs3PmK.>gV`Bx]iO?)k U`믧+R4j60T oPȒ )[㊖Wb/BA#MحB.ƷaZ3-eUJ$m^DӑJ% hn:ؑ֟p_EYV]:=*=(GscPVpG!XP'Gxey˂E_`"<]|/%ny5|YɏNV0pPߝ&@zz/NsƲߴ`E~L@4٫w R0V1N@ q<#"kJ*".il'c@C*Đ+ xך=[&;`` Ζ_&w>dvRoF&"R@I}n),jZ/WW֑BVX|$`b~]h$ DM^o)Zh/%wK.`KL7-S0jFrpa6qm2b`CÄǦ<@QL5mI/\zr׾$%r3ڮ ZE5z\LJ ]ܻɠu;#WEBELrj'ovpÒE,OߩʷCA '|i+P6Qd`h`'Cgn#*DDk6@:6~8-dtٞ(Km1"=tL(B9\H:Y.0# nlƨs/kDx8xk!@ZAk OYa:w1DiޒUϥg=̊NڠdZ^}qIE mz j9F$:BD('KgRɏ! )P#3qpϙ u?IB\E`\:Bڔ(-qn\k>1mwP(#ULw栯PY;'RpʕQ_[ZN`7SޞCvD^ q21۲)N8HYfbz!E{첝@{0 ңn0YxhV X{ ;&:PFM<Jబ<QY/ɂ} 7$d۶ \K#Z@zt{#J_7$I'6 P1sYrqlF"B@/EG~e6YA1A6X$7P?17HD:pL*O$y_u8՘8PhDB"#y bEM["ly6[x7dq\M&ްx@9aEvΨeߙ3鲸WE&fLΖLI!_2v0c)ŀZǵJAnp2Ѥr,58wAl4_+ jbnNF +"|spo`u-=PֽI@ -v)@zwDٝx6q*U~iY# ͖4O~iDV3>Y03ۥxML$D>G.fF>]B'WU"`[Qiw 7O,x[{rcz#qSpRi۹-#7S r̼Qqx E!Yy"|Qm@Jj #hޡ]eݻ1|l5^E6g&kCIIWiMc #qʉJ^i ywH#i'vot<%HdmK1_<:Ѥ3a]~Ҙ@iKamTPqi%c&&&}NVш[v:b0L phw+4>ieCvQ ;W`䌟Sq~/Ͽ;+Kz+b' #8IČaVʛK0\@wj+[_;"%_jJ\1N \!QN|/cKŌ L:hu^Qƈ5]x|W5sS †PY(*%۵-:|3~ J0dl}3&OFfyR&gٍcuoPvtFnOi؝EO Cū-jiشar,H/J#R⬎2 qtJtaP&Zp@*x@a3=&ڭYQNZApw~R=in մDRP(Gq3ӞtE#OƆj-&,b?77`azlͻY]&z% HSN_,Ð*j_t6!s/o+tE/n;0{ӏyJ}~5og"YX rK]9pIk"s/8 _=tD=>|o%{AE9)\MrYfZ4d({Рh?á+7*h_ Zݸ$*oZ2:bn)c# >gW> oؖO8OM^x[$T"m%y&&(ފo^hܼ>K#=^eM3:rt)g޽ɺzRkb1 D;^uaT-x# D{/IgOt ԔK#S/tÑsךR0PA\k`w-Ā/R kR^\쓋ىf>]#ici`3Ao_)HM8/M@el #{ų\,%%or*Y)UW܁+w (ASpn\uV87T(BH˘e뮄F,Qۓ֢Dj;-MKz 2%XpץWl^TMCڗr9:%{!W5Y ByNB›X3K(O Hm+uy;pZTL2GbY^Ls Fv ?1xfbk7M}c)wy E\,iذn deGҧC!`Ol%9exG# m!D9؏qMb-'A'nBgϾp)OAUgEڈiZ#{k1+LQ0weÑ3_!Qܢmӟ#ڃM}}@Y8%M  I~-7R=<59L^ dQuTTq 4M S RcD{iVG(ů6*=*zśy|:wP3Y(FhxA#*^bE Mkw9_GW;0]c?=_'gig<u #;8''4%+mxw'jWHIpJm5^ , +mˁAIn幋{%Y{sCdYGC2EԘsՓ_(T{"#cU-cBJ~zFC\'p2edBbx3ɒw/46sMwf\-%8>h壀)dZ_ pst~A'ul *9v"kE4ؐ"ؿϥ,Hц=nk:l_I{y^:lcI|dQɔ3+gZvfdz4)B䭾kLqc^6 ؚz,n")@!sgk!˦`EWv0Y{Dս-,lHmVOkN?wmnI449 x׸x O:Jf.]$1B W}6L 5'M tB:E GW*\8wTƌUUS\:̐IvHƁykU)@N견d$. kٰ.R ҫ)O kbVHV#I:oVֲ9֫O`Q3{Z?-_\Zδh Jq-/pۚýeL1LҬ8 {GFºSu5o`bXN.EPIwR+N E~H$V|BA:p`zN[+5}s:UeQN`L Tλ0vHA }ڵ0Z2Ooy 7HA`!vYB#jܜKg:P&% |RQ+num(,mJw喃#cClz-XWĸm!KL;덺hh)W:]x=? ٗ/ilXċHĴdX ݃vFK"B^#'Z[b.)@}Md2 nRWߜn]@d@tp EtYxMʹv~b(p<*RhW_xwߍ* ٺ#LB>NNxrLm+v&]>?l2%s9w5|I(hveA͑c&uPt mڔpP34eW| t»T 'S6u) B0pC?e*:ztIBX %JD:NYLu 5WZ%$iG@dBJl H*¼U(r iU ܠ2xA`"!B;J~Tk) "5} !RmL3>kޯ*xʱvPr>OP@My){ZP)gi85ʹ`ZVh1/+/C& MeWxg= K=+-y?r#O10aVb(8>E[3=ҲT Y%#؜3n(Dd|\;qɬП[4evʳt<-OOar~73k";0qmpn7P^aԕ<4~/1o6W NF!^I1}p-dee :쾮ub#E^6K RzUƛ8NakoESGBJ䔟Y`t|)pk=; O "z6w 6qҏ9Ty9i:v} "tU[n9F)T(CwI4e?3DKX(HfޱgdsGXSk\-P>u^iAYqdp}cbP hk"$! Δf&Βm/B߬џKW˨d@`-QuSM˞Y ~'cϫ-ǖ@q<J~Isʹf;z#fvu0\߂*=bԕ0%&/o31۸u#wo^s>qI{r$,8.nE ȢZ!%9JlpT-\(h| .e=pkLH}A€x}*|Cm D!tS#=}{Mm]YyX3LOU+hϋ=Iʷ~OT>M:M<Fp[ a3D;14(ӓҍt,w \P |Qc9V>~37Hjey荚"#nQ"\;4zDhQxA.[\FV ; >/]A#i'._j5kLyk9i)!w0y-jkZU*4`'mu{~&Tb\$&wv>˽6|7x񇼱 qxgK3lZPFu>`5I7=Tё6A)[:.ys Dg*|r fT:q7 4`V5k(IvP-㵦;1yun-xZU=U`knaiQw/E:\t8 m) jylZwB,~UGQ̍PnOFv, \"U]O2nuyƲyiYY rr@PԘWq l3sV?n"}+]n(zm J"0%8;4<';}ϔh7J!xn{kH\9Mi< #^iT9wX X{>'bvn!.J9cPuizEmSzc)'-z5 Q>'^)usbGu۹[CX3/C?{;iE*fs۵l&% e/VmYx9,IֆP!A/ye9X6[UTr wj S(vC1y8 ɳmM{ƁrR.݁ߋfoqAY̌}/H@sXۏv8ؑzP7M4'E7*K>̂\21(ě'$yD^)cn7fgU=nVdnQ?nGv!6"#4R ,V,lv/ё$bdzg$9p a? oW6<lN#roӘ :pnoS|JH?N8&_zoy+RgпNF,Aƍ]TTGlM%[w!^!mGU Vwʉ6hzKo8u)>9Yu}T=N{Jd7Fvdf9Ք50Hex'`I mf9vu>x`kU"hf.DeN`4H>(#x#뀬{d AĮw owad+T%C߫fq\a~^H2ԹtM503ˊ,Ҵvo^A?AJL)N_w3mx6O~U-A/t@1H{h&hs3l7pH\L⧸J-7US]6#îIA&e!kj~w' q,HPi@Kl1{ n ƀN  ēo弱{F\%!j[,D@0WJgЧ%#-dK WQ_E8Ռʼn;^>8*XqqV@qߩ@dԯ1lہG3 h$P;1k\{u6n![_G ^aT=&NBi!qKL]HgZleY!Ase92'V'GML[粿iE8 0ץ,I\- /}oiG+D4 Läl~ҊFxYB,"ȻG@omJ/ZwBXD:VA-7z | b7%Aה|DD;SK,!GaDc7nDxjtoE.3Sj0I"լۑn1k]q",9a'pT@bqɌJ@+ ~+6jʟ뉡khSZxUᆴ\5an`7EHkgMPn0HCtuon%%##X[[A%2RۉAy|Jog8BJH(2{5oΆtP,"!^䦍&fOuԴ1{) DZ >e>B¨|KUxD^aFg7mvj B '~VYe|rfͲxM 7L|WE!ǖr+$)2՘tU}ht#XGTo06.C@вdӀVt٩?)} 8Fa8:ND0m`9 4*PQ3Q8cm@SqTw]יGK֒rEt\Ky=vVT] Gq]{ZN.: <")èRN- qmG0]!p(^h*'P"DTЭ/VQww]y%A)9'GHrDprss.9@ĔynRWRHpEt\Q!8$BPK;'9RT]ךsfyjJb쳣 *(i&cDPɴtupKډhY|5mZHHQ+شS r$.p: qrtKYXyR'=8μv֧:N(A$9夑@.RA8q!Ĥt hm JqHs6w:KjçCXl[gIdr9 {uCqΧB&"";o"q.9NNNH.D$I p"=S8?9ʢ(y5(hGDHZ=:"8:H8r{vu9'G98tȊN%-Ȋ %9{[2(ݕ'UTRB!B&VB"D@hJ*% H)T U@B"DJ@4 @TRAbsts!' )Zܽܧ!9sNq<7(㻮%""(E)" -b" UJ ЕE]iWwtGn00ZB99 ! q!*c5 *i:$r "ChTTRRlNr"NH'BD1ʑRQJRBG0hRpctQJ*P P%]Up38P[Z]mIIМ\% 5KH=AB*Pg'!;:H)$(N R _l5"AptQ t: ,.pH!::NY7Y=#Y{׷NRqa"\/j\HN=jI'"ttJQ$9jqBI$QG"@hTiDU((TTEQ(fB%("DerL܈8\@yM"TTRtH45TSs8)U(D)X]]S@r99Lh-J4%l1MUl:bVNJJJh&Ӂ*hhT(XJP+l-- (P4Y]vgX3G!NDpDybtq˴q.D yQ:RI^VnHvIE$8'tN~ YI.HjZ3pIQ@%)G'h:kG"q 8g$HBr9P ĤPt 'TOl$tH9 s#mQJ!Gt!;s.H^B"Aӑ[hN䐊RDGqN(&( (JD*R"P @` fdΰFD:r*:"jBbtD h(NlGT5Li.NBVPZTU@PDPFHβ9:;DFfJU F)PPFbhG 䂱"  HB!@*@AtmW`8%3[aӸQ Ien9CDHBEj!9QrCJ .rJ ;;NL8JDDrڭk')ns9<ԅĎ9I9BkjH$B%{V)Ј]wT Kۻ;) *f() œGGwEwQԔDU͊H*$(PHsh" !Q@ZI" FQ)ihUCt1QQtB% A15$۶Y'H)L梁w9!n EH"I.S+Gt) rtN TGG98tSHwGu-D\ȺB`TEhU a h1CM*1RDEDT[fU4*A*!HAU %(((DL" HSBPR P)T]WP([Z8$t#:{`p8^v !"$p]s\D*(&PJ&ET(UARV(҅'..8cp"B$PJ(VT(QH('"!":{]RHHC*ĊRTCʸ8HGHEDHBM(( }CA-4LG'1 (RTH1DLBVT))F$( *@*iWD()Z UPDZPQ*BE(AQH(hSB(t]&Z4 %!@  RH B4!JP Ѐ B"P(( @- @R /~EOx'/G72??:GG~S6#\խcAP(4"P@P( ""}ϭ<:V_D +JҠ qy(w/oa(> >:T&J?5D~9\OX(s Qs~;H9۷OiQ(CȨ9 R P ~o____^~J"*( JҨҪ4 J !_7}>J B P8/P 2_? {~Sh -j~1lnҟ_@?_~~cVߢ>c x@R`{1~]>{2~N'J>Gv;| F=C4@{`/Ae !d7lV` a7("^ g7mo}>a d[_#;z;ion]G]ov}/93_ ~nGr#X$;`0cͿa#? C|`4qq9lDyT>EXh s"دMIAD(?Ea,ianݮ' r *nY@<ޛ!3r4Iu QCFr8C($\4LS}8xC"lr$Nq^1ѩ$쌄Hތt0XxO*])T[<.L@-BPDD$aY҇^uPau3bU{8G)p0#G;_3T'J.)>[~1G-蚬8Y~J: Yw...5by^^Xe/ÛR9NYۤμt"ԆLi )7JD XȔɰ13@Wo\ nYyX8D8g 2]s+wd$hI=6? #> A¢gbcXXVIjCם7Hԇ#zQԆ0k7fX*YLn@$P݅ӧ5K vӞ^iYNTyfNɶi4VrKٙUDh<*EULIud8+YG+䦁gKKgi4 Cߊ~EOϖ^1NihEI;f qgN8 RU6@nt)3@$8391EK,1f Ǐ<2#8Li+9Y]2|˭%>{hk=:duR'IH {&l! BHd<]p @F!rfr׬6pFXFrR5.PU($>7+|$9 (𭓆x#,|873JGPIMYH0Hx4T0x(]#5r!O8C1f#O<# ;adlrXϕH޵?w?w;wǟ>B0/#~Я aG6_1П|T5 `b~?wԽ:H?ܙL!}\"hdY?ϏhNki!0pڙnس)wN;Q".GI zg7q>/u&њfNbi${_=6fH4Bn?&buֳEh$Һ^ 4aCmr:@r7]WD8i7nN*sTe-R`A:t1̺1 dQ3 :"O)S 2Y}ŔʹH#Ӆ3IJs'!qd\@ ( $Q&t Jxf$I:c┉we:g55ɢgܒZ̟z)!d遁$gG\uo=H+q`7lxpiIS INޯVo:\4rSLWHX9K Cy('a읹w$S 7forcats/man/0000755000176200001440000000000014004327013012460 5ustar liggesusersforcats/man/fct_inorder.Rd0000644000176200001440000000170113626262603015260 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/reorder.R \name{fct_inorder} \alias{fct_inorder} \alias{fct_infreq} \alias{fct_inseq} \title{Reorder factor levels by first appearance, frequency, or numeric order} \usage{ fct_inorder(f, ordered = NA) fct_infreq(f, ordered = NA) fct_inseq(f, ordered = NA) } \arguments{ \item{f}{A factor} \item{ordered}{A logical which determines the "ordered" status of the output factor. \code{NA} preserves the existing status of the factor.} } \description{ This family of functions changes only the order of the levels. \itemize{ \item \code{fct_inorder()}: by the order in which they first appear. \item \code{fct_infreq()}: by number of observations with each level (largest first) \item \code{fct_inseq()}: by numeric value of level. } } \examples{ f <- factor(c("b", "b", "a", "c", "c", "c")) f fct_inorder(f) fct_infreq(f) f <- factor(1:3, levels = c("3", "2", "1")) f fct_inseq(f) } forcats/man/lvls.Rd0000644000176200001440000000246013626051403013737 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/lvls.R \name{lvls} \alias{lvls} \alias{lvls_reorder} \alias{lvls_revalue} \alias{lvls_expand} \title{Low-level functions for manipulating levels} \usage{ lvls_reorder(f, idx, ordered = NA) lvls_revalue(f, new_levels) lvls_expand(f, new_levels) } \arguments{ \item{f}{A factor (or character vector).} \item{idx}{A integer index, with one integer for each existing level.} \item{ordered}{A logical which determines the "ordered" status of the output factor. \code{NA} preserves the existing status of the factor.} \item{new_levels}{A character vector of new levels.} } \description{ \code{lvls_reorder} leaves values as they are, but changes the order. \code{lvls_revalue} changes the values of existing levels; there must be one new level for each old level. \code{lvls_expand} expands the set of levels; the new levels must include the old levels. } \details{ These functions are less helpful than the higher-level \code{fct_} functions, but are safer than the very low-level manipulation of levels directly, because they are more specific, and hence can more carefully check their arguments. } \examples{ f <- factor(c("a", "b", "c")) lvls_reorder(f, 3:1) lvls_revalue(f, c("apple", "banana", "carrot")) lvls_expand(f, c("a", "b", "c", "d")) } forcats/man/fct_relabel.Rd0000644000176200001440000000232613626051403015222 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/relabel.R \name{fct_relabel} \alias{fct_relabel} \title{Automatically relabel factor levels, collapse as necessary} \usage{ fct_relabel(.f, .fun, ...) } \arguments{ \item{.f}{A factor (or character vector).} \item{.fun}{A function to be applied to each level. Must accept one character argument and return a character vector of the same length as its input. You can also use \code{~} to create as shorthand (in the style of purrr). \code{~ paste(., "x")} is equivalent to \code{function(.) paste(., "x")}} \item{...}{Additional arguments to \code{fun}.} } \description{ Automatically relabel factor levels, collapse as necessary } \examples{ gss_cat$partyid \%>\% fct_count() gss_cat$partyid \%>\% fct_relabel(~ gsub(",", ", ", .x)) \%>\% fct_count() convert_income <- function(x) { regex <- "^(?:Lt |)[$]([0-9]+).*$" is_range <- grepl(regex, x) num_income <- as.numeric(gsub(regex, "\\\\1", x[is_range])) num_income <- trunc(num_income / 5000) * 5000 x[is_range] <- paste0("Gt $", num_income) x } fct_count(gss_cat$rincome) convert_income(levels(gss_cat$rincome)) rincome2 <- fct_relabel(gss_cat$rincome, convert_income) fct_count(rincome2) } forcats/man/fct_c.Rd0000644000176200001440000000124213626252103014032 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/c.R \name{fct_c} \alias{fct_c} \title{Concatenate factors, combining levels} \usage{ fct_c(...) } \arguments{ \item{...}{<\code{\link[rlang:dyn-dots]{dynamic-dots}}> Individual factors. Uses tidy dots, so you can splice in a list of factors with \verb{!!!}.} } \description{ This is a useful way of patching together factors from multiple sources that really should have the same levels but don't. } \examples{ fa <- factor("a") fb <- factor("b") fab <- factor(c("a", "b")) c(fa, fb, fab) fct_c(fa, fb, fab) # You can also pass a list of factors with !!! fs <- list(fa, fb, fab) fct_c(!!!fs) } forcats/man/fct_collapse.Rd0000644000176200001440000000205013626261320015411 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/collapse.R \name{fct_collapse} \alias{fct_collapse} \title{Collapse factor levels into manually defined groups} \usage{ fct_collapse(.f, ..., other_level = NULL, group_other = "DEPRECATED") } \arguments{ \item{.f}{A factor (or character vector).} \item{...}{<\code{\link[rlang:dyn-dots]{dynamic-dots}}> A series of named character vectors. The levels in each vector will be replaced with the name.} \item{other_level}{Value of level used for "other" values. Always placed at end of levels.} \item{group_other}{Deprecated. Replace all levels not named in \code{...} with "Other"?} } \description{ Collapse factor levels into manually defined groups } \examples{ fct_count(gss_cat$partyid) partyid2 <- fct_collapse(gss_cat$partyid, missing = c("No answer", "Don't know"), other = "Other party", rep = c("Strong republican", "Not str republican"), ind = c("Ind,near rep", "Independent", "Ind,near dem"), dem = c("Not str democrat", "Strong democrat") ) fct_count(partyid2) } forcats/man/gss_cat.Rd0000644000176200001440000000142513764156637014424 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/data.R \docType{data} \name{gss_cat} \alias{gss_cat} \title{A sample of categorical variables from the General Social survey} \format{ \describe{ \item{year}{year of survey, 2000--2014} \item{age}{age. Maximum age truncated to 89.} \item{marital}{marital status} \item{race}{race} \item{rincome}{reported income} \item{partyid}{party affiliation} \item{relig}{religion} \item{denom}{denomination} \item{tvhours}{hours per day watching tv} } } \source{ Downloaded from \url{https://gssdataexplorer.norc.org/}. } \usage{ gss_cat } \description{ A sample of categorical variables from the General Social survey } \examples{ gss_cat fct_count(gss_cat$relig) fct_count(fct_lump(gss_cat$relig)) } \keyword{datasets} forcats/man/fct_rev.Rd0000644000176200001440000000053613626051403014411 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/rev.R \name{fct_rev} \alias{fct_rev} \title{Reverse order of factor levels} \usage{ fct_rev(f) } \arguments{ \item{f}{A factor (or character vector).} } \description{ This is sometimes useful when plotting a factor. } \examples{ f <- factor(c("a", "b", "c")) fct_rev(f) } forcats/man/fct_explicit_na.Rd0000644000176200001440000000116613626252103016114 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/explicit_na.R \name{fct_explicit_na} \alias{fct_explicit_na} \title{Make missing values explicit} \usage{ fct_explicit_na(f, na_level = "(Missing)") } \arguments{ \item{f}{A factor (or character vector).} \item{na_level}{Level to use for missing values: this is what NAs will be changed to.} } \description{ This gives missing values an explicit factor level, ensuring that they appear in summaries and on plots. } \examples{ f1 <- factor(c("a", "a", NA, NA, "a", "b", NA, "c", "a", "c", "b")) fct_count(f1) f2 <- fct_explicit_na(f1) fct_count(f2) } forcats/man/fct_match.Rd0000644000176200001440000000161013626051403014703 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/match.R \name{fct_match} \alias{fct_match} \title{Test for presence of levels in a factor} \usage{ fct_match(f, lvls) } \arguments{ \item{f}{A factor (or character vector).} \item{lvls}{A character vector specifying levels to look for.} } \value{ A logical vector } \description{ Do any of \code{lvls} occur in \code{f}? Compared to \link{\%in\%}, this function validates \code{lvls} to ensure that they're actually present in \code{f}. In other words, \code{x \%in\% "not present"} will return \code{FALSE}, but \code{fct_match(x, "not present")} will throw an error. } \examples{ table(fct_match(gss_cat$marital, c("Married", "Divorced"))) # Compare to \%in\%, misspelled levels throw an error table(gss_cat$marital \%in\% c("Maried", "Davorced")) \dontrun{ table(fct_match(gss_cat$marital, c("Maried", "Davorced"))) } } forcats/man/forcats-package.Rd0000644000176200001440000000176014004267615016020 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/forcats-package.R \docType{package} \name{forcats-package} \alias{forcats} \alias{forcats-package} \title{forcats: Tools for Working with Categorical Variables (Factors)} \description{ \if{html}{\figure{logo.png}{options: align='right' alt='logo' width='120'}} Helpers for reordering factor levels (including moving specified levels to front, ordering by first appearance, reversing, and randomly shuffling), and tools for modifying factor levels (including collapsing rare levels into other, 'anonymising', and manually 'recoding'). } \seealso{ Useful links: \itemize{ \item \url{https://forcats.tidyverse.org} \item \url{https://github.com/tidyverse/forcats} \item Report bugs at \url{https://github.com/tidyverse/forcats/issues} } } \author{ \strong{Maintainer}: Hadley Wickham \email{hadley@rstudio.com} Other contributors: \itemize{ \item RStudio [copyright holder, funder] } } \keyword{internal} forcats/man/fct_unify.Rd0000644000176200001440000000075013626051403014745 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/c.R \name{fct_unify} \alias{fct_unify} \title{Unify the levels in a list of factors} \usage{ fct_unify(fs, levels = lvls_union(fs)) } \arguments{ \item{fs}{A list of factors} \item{levels}{Set of levels to apply to every factor. Default to union of all factor levels} } \description{ Unify the levels in a list of factors } \examples{ fs <- list(factor("a"), factor("b"), factor(c("a", "b"))) fct_unify(fs) } forcats/man/fct_other.Rd0000644000176200001440000000164713626051403014742 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/other.R \name{fct_other} \alias{fct_other} \title{Replace levels with "other"} \usage{ fct_other(f, keep, drop, other_level = "Other") } \arguments{ \item{f}{A factor (or character vector).} \item{keep, drop}{Pick one of \code{keep} and \code{drop}: \itemize{ \item \code{keep} will preserve listed levels, replacing all others with \code{other_level}. \item \code{drop} will replace listed levels with \code{other_level}, keeping all as is. }} \item{other_level}{Value of level used for "other" values. Always placed at end of levels.} } \description{ Replace levels with "other" } \examples{ x <- factor(rep(LETTERS[1:9], times = c(40, 10, 5, 27, 1, 1, 1, 1, 1))) fct_other(x, keep = c("A", "B")) fct_other(x, drop = c("A", "B")) } \seealso{ \code{\link[=fct_lump]{fct_lump()}} to automatically convert the rarest (or most common) levels to "other". } forcats/man/figures/0000755000176200001440000000000014004267500014130 5ustar liggesusersforcats/man/figures/logo.png0000644000176200001440000013154013626051403015604 0ustar liggesusersPNG  IHDRX?gAMA a cHRMz&u0`:pQ<bKGD pHYs!7!73XztIME 7xWIDATxgG}5l{̹:ՅvI#ʍ A }Yi ֌ F{sۑ&tU4ES2GӇ +Ev=2YQ}yvϿ< (v>+oRwMb{ 7wp%b ū]0?- Зn%.w>%;]w:?;%]B(o8>=7P]%;-ĕρ3@{ɗ4;]"K%;}@j~D\|p;x]k ߁wsK- 1 ?u%N.wWNsO7>pػDa%C8~w[5:%.2"n?9ou$?6:%."W/NmquMe]E-` q>忏ߐy7#<~c.v PK7]ju7ŗ.;HOO] `cd~#m7 .wHaW%cgnxؕ->'v { }C?dWXRaW +oؕ->_-E2 -W,{߰+[WD]6e;p[ᅤ_}mτˬN !*:z@~-Cw$@D^oy["-"@u,穭۾]׋-~=ލK2?I5N k*9\z#"FPW._Q]Y^!wpS?=-W!y}]-)сG( z˗/8]}CȪU|a JCnݺw} RQTYU+훶!#߻[]7Z7~HoQwh RuΝZ(?4؍ʛA$DKtsUΜ9C<\edxbV6^m?Row}";>QB5*m./_&J1<4X47_C(`z\ի:tq"쓘| elϿ<^Y?twx/d~(!H2JQ$3;;ӧQUa3g0??twIN 0;$m񮞏)d~g}4B{XZ`uu'Ow~FqhZ4 x[ޑ~jd~>%I4R??|79rH$B>gssZF¶m\k'(Ȳ-2Z>3t]￧ZQA<E5vF?z5$K`s'yxWx>AϚ[w}W_}W_}ŷ~O?9088eY *xR$IȲLn;8dlϿ}姾ߕDi}R;J'6.Z4 w^666( VB!"8Z$}<ϢŲh j$!ia$EEDOlx׶I$ヴ@#udEr]^S_qjqrT AXZZΝ;O eYF$TU\.G(buu~gP(8nը>us# ;U'}F EY?t-wi6qqd,"+xgT0ؔ[X^Dr9 a:BLFvF0" lݍ}]~(;"j$xJ%l&l6Y[{5ݥyZ-J β뺄h-B#xk<yb@%Q[ԱDID33?5סfil"GF^C k(Mz*]=j뺻D~uH∴o/e5 ε+++O:feeZm?ϲ,"sssT8!MES~m0G&2Ze e")~c;Aۣ(H,+ױ]4,buvA$>L_\^C:IY'lWHLjg\ͦ{KWHSw.$=3˂@ZܹsDQz{{4myG^޽{,,,`xp,Nr}#|-*8~h,)~,)B{ 8˲XHUQ@R \ϽNp퐴;XRRb7\VP4sx={p&&&X[[{RekX9‡~. (`^"5yK[HM ޞlYRo]",wfXQR0M7oRVQU$Ibvv:TURlRJQF$ןKйW%DIĵE^UEHO3p>޽{4pd2?ܾ}VVH gFضiOxOGm1`6h20l7u9KD~a;C`E yGww7xD"iξdu󬮮Q"IQ"&Y~ɖTg$!h*e1؉N-K(ȲDĮPh4V_0442ΝcyyUU?$͢( ru}6KKKut]gxx zzzP4eY棏>b1 >ۿ7Q%̥ T-; `E4 "ȝ;whҧ^H$&Ȑw BdONmI^9ew v]~-"rN4͏49p?2== ~!VL裏gjj uh}i_N$2>>(T >ˡCw7s_z줺~IS7qvNϋw.".]T*Q(XZZ ܽ{k¯ ˲X^^&If(*i{Al۶?Mkے$RGeJbp5 àEQ󬬬p<ׯ_4M`jjsαNOO{eppA8ViZ\z7n,A=22qf4-,uDZo햝wl1ݴ,27eaayn߾%۶Y]]%ɠF4,z(Q3 C-?nۖ( lfig8weuu`fѕ+W8}4zA8x dgrlۦ^@@u0m/۷l6yhF<0 DQB¡-M ea`&A4j9e DP0 ܼyN0~Ԏ(aBm mINIt?<{2=7E"ׯ_dccAt]woe}}FAoݺƲ,VWWsnb~~qh6K__]]]066Fwww0P4$I-s_CSvjI-s(8冉eY$~; 2vd{a$l6K<G~Y:$$Ezٯ'p\~~ EQ/HR>}bssreYO{8Aw޽{pyTUEQΝ;Ǚ3gexxqJ2q]vj1$zzz%m(P#IXFΙ3g^kE!"l1z.E!B hA6d I!m8CRHjfݥ rYDQO?3gpu<ϣZ駟_s9nݺ\a~9:?#BK&&&XXXR)LA{]~XmU DeNf 0uo|ac|ƎށEI%5\|7oKRJoo/'N>?31 MUIub^wKr-)R w2ԝ˲HY sNL>0 ǙիAx\.3x6˾}r,p_{e||SNVX0$b?{~~O?q tLA%5}v1P~m4]ZUyXdXy[k$) EQT*ܼy7o2uwwDڋ@ӑC!As=&aDVw0&yW677V5=Q^s_옱X MEqO}NpuuP(mYBE~&W/j*'icL-XY_Uw&;_#B\fvv\F"ɓi0r֭`GڊA4M >. JXz Y70`_w; h4sN֘QU#;EUUdYy3LqaЏ)(Ԫ;2a8ΎR^= 4 ,Q( ݕf7H8ե=Si:Jw;c6pd2an"EOOM:&,˔J%6K%fzepmj8{,˾A;bu?8ofKC{4J/; |=p #C, m~-w D蚦f%?h4$Illlv6sVK5 qb,Q<}6oH 5v*:=ϣ*4uG."!LE>%`u9˛f CO0)1yHL.eo.Fծ3&޽{Xr9r$hx"pu1MfeY1J/ 8p!֪ "K\|9贊D"@^߱ X[[g+ 5h ¦a^$Fnw{ 蔝*% ƙ#S:H2bPzx#*w@n6KKKeB(ٳGDizR mted2El… ܻw}144LKOx[&.,HF㍻k :rJ"IM4`gt|"4I])LA-'x zPupKM;xd[|q|rj5Y]'aE!Յ X8h@ n`O+yf:2̚DDAGJH-=Zue2MO\ob;d8rxt1&/%l  Nܻw">5r8qMdjj|>8B!طoH~0ry[[.# k2d20at]~(1[U1mfL.˜={qu=ST*yjPa6W\ٶ~cI O ] 0 & t|dyyyG;z*100Eܫr7_[RY QfڵkLMMQ$N{N zfRTw{=L[P,57BNC#[9sx_h4z }蝫غ4ړ)Уdr&LRyem%_gC~Ѣku2պC ճH uJ{oky駟 VΌ޷a#28qH$70[Z.ƐD"d2Ǟ={( 377(^'EԩS %{rܓr&!>ZHSPi: Q!hBaR*YY^fqqB\NΣR<ťq=s7&-ac=(}{2-Zvm!Eߕh>W/l\|r0.6S$< Sp3x؞H,܈NcӧX󿪪tww399do޼ə3g^{q666`zzL& R)r`ee%z]h4(J8`6( !6"Ҳ,*B ju,p8DC$Ro($`ǣ)3Td%vW"$QuM: u\,qT!BldMX1PѱMplV$3boplnnIww7CCC Μ9\õW($ &͢*J)xj/_'8/w˥R9޽ƶ&:S u]<($II< woR(jjeUM:?T*hUU X"hk}u7(|֓b.9ĵu-/M`]ӛb_ B Mݔ:*#+r0˱D8fhUkӪ5p,%+/Ǔ=lŬ(N%/E;wO\~WE( Li׮] &3mun߾ݻwI$ 2<[)=7cKl,KTl.ΖdQUb6%PdIPí<,FE{I"k(nڵkX _5044===hFzyȑ#;v R?[n?F#镚m9 P-}o۶-KZq۷1M3pXZ$II( 'pW"T*r9Ñ#GH$eYp5~\"Zm[ LNjޱY\\dnn.irGfh4J. vṹWDQdbbl6ŋ}eBQbxxfwbQޖn?MA%/%X,9V4RTNNn3@R}ӳ ICGs QU@;e`4H;ݺ{I.)~ؽ]$Ӥi"Paٳg#w/Z-HbtT*E<GUU333\r/r5W_}ʼn'@HӄB zp]wKRV+hDu2 d2677_^344RX;ܱ1N8W^}VGU, tww#I.]ݻD( aD\vţӎ %)meE!RCdiZբ)Qj!1`7ySP 0/u1MO33s[fT 4XB)-zC""{-ہ0c9#qD>>$")nu$}[˪"M3TXDe lۦX,,hqY]:NEcL&ٷosss|7Ɲ;wXXXT*8a;c===B`hvm<Բ4_\.ׇa5n-LNN266ٳg~hvv7oRTPUx׮_T|29(r֘0 &&&Nq_h?}(D"(hp˛'VEQ@D򰑸65ٳgOV>}]70{ۥ1ܟ³w}Du=\IBJТ)pV ha EUMeZk tW#$?D򰎬A:Fpxl$۶) OC7|0 q)ϝ;w{ /1qf裏ؿ?ܹs@9.w^>R?Ӷ%LٳˡCi4M9>X~'xGWWT~aG4 666BUՠu(~)TeEQ'Lo>Vpc+"\}Vw02/@4fgg%N.ZRDXZ>X9{,x<(MOO?)iy'3qMϋt:M"Zyu"'+(EX@oWwۮv b$V!O}m)8vA$%(5DA4dYV+Xq^KSYQ;mrGR@q ^駟r Nxxs WWWr 'OСC`;VT*44MVWWY]]}{l4A3 `:B:uIOZ7H{5t+(-z46K؍s6Gn r&C<\_!#Mý~BvCNZ$tNcZ l ;mr̥Kq7npE>\ejj9hZ`ϳĈƍ ޽{矟[8d 9vj#4?SVE|^i4u¸ѶlaT2hpUd]b J4{eñL*-*57p(֣$l7zLX]]err?? vVS<`z=s->|UUσ]޽{4D"AOOr9;wHYl255E.c||7o>5[!@&g>cָtRP=~8\vUgdm,C&pAUUt]hyB^~ۿA<'UILden-< 2M3+HR 2448cccyn߾Yv2r…'Np8L.CUUjФ<B>|RğeZV<4xi42Ǐguut:CwO7(2֛b4@tgCHhDj϶o$Z4bgD$eHou&({PSUzHCמ*$ 5u,ˁ& D"Au=̙3E"b;Y\\KKKضAvV%:77fggQU>O>ZH"ɲW^1O8x DV }}}pڵaAx.www駟ҥKAifq~7nCN<'3{ynn.(qp!&&&XXXޅBT*Eww7w>_Г*}pӧOS.d2LNN_sܹg QpzG]:>|Bи#ys308D6fKd Ϭ3`H $,x4M\ǥ^*z< ߢDTI\NO$>fccˈDI74k <̆z ۶;d2d2RH$dZE٤T*QשVTՠ3S$I&''T*ܹsδD"G :qX__g}} =660~$188c eY&wԩS|J6x$I|gAHUU駟k\(iR)%J54rQ*{Ud[^0|\@KZ,uudAТQDI^,6f8sO'pmm!)jj"@m#븴SGlEv Dꢷ7P _mFA([VoT7Y9z(hϿM˲8wtJ•+Wa``IH$ȠP{V=<<w &Ug߾}8e*B4iZ 0H$ e9H&)J_ĥO C2B4B,vl RȺ H†Oju %S c5[.# ˤaȪNxt?ZjͅX*դ[(P裏D"A產([OOOԱ,jʽ{Wygyy7i]T8Koo/DGҙ= ./_&N_i$^[[_EX|ƞNʕ+( {uV%"^nd`WjM<ˣJdi 5Em#O(B P pNUSsB4":Lzl>nc ױ!A@n։8A z;Ff1pŠ~&iV!V9::7e}A\&0<>8;]aq)\r婝\.===Q)˩i>#J(BXaGˠj"zp%d' Nk7xxȚ_uA;$6MFVeUn޼]eYȑ#=zVŏ?Wy011ׯ_eYa<Ⱦ}hZ۷_d'cjfn4,lRg}}bHV{yB/{PExLoo/W\AeD"M .NP =Algy}EPuE D+lT &j{הϱF<?6jkNE7;g62h?"(q<ˁ0@u9B.*I;vH4,@XH.)ԊÆY._LVHDQIJ,666}6w}v\O>$HBW6k4AIJ]d3L3nnnR((__ST?30nݢ^4?~:p, (QP1d*T c*-D42Z]UKAln>2)d F&LjK`srgΜ6 Cecc#>YӰ5xk?& ,zUUI&R۷oS# |8~Usc7}<ӧOsG0UUd20<<̉'ػw/sssܾ}|>eYȲ8p۶9k F]Ndr zTT_(d4x?رcz>p@гƾ}VLMMr*L266S5ʝpa~)esƍfǡRp=i4@Q smhǡ^3f-sUr Udɗ#[Hxv[8&R+/tdU(BҗNͮrB<D˯hMf/"UPCDؓ ;)̫ b8rv#s癞ۏ ]m(dp|>Ͼ}4ׯoˀ"N=x<_ڊNdY~iZƵk׸yf࿝d"F~Ll\__f:yϺojA};綪A]X,}ײԊ\!;O $qQ2 W\y, "iسg!MJkÃ{ $r!PDcX7f8H r4 a}}=8`ϵ099*/^|}i|^M(bݫV=Yӳy$9뺁1vrE";7n`zzG{ɤ_xY0sqUk8ܾ}u/9bsCI(DA [l+V'I.^VJ0;;GHѰ k%+@w7Eí[+ԩSsi:{exxsqڵ M+iΟ?ii,]g\Š<9o Bi_(:(j6\~EQ$ǏtݣT*=I&FtejjQ*p\I}y. {χ~ӧ2Mp/#fx8Ӏĺn:ȑ#4M\lzcVx޽O?h 矓f|w  !K-za Hjz\YI淿-7nڵkA9aȲLOOO0 EQm;05w]7366~ &&&8~8xΜ9RPgR}ww7׮]od.T*(8ֳWv qiQΝ;v:4 R 122 EQ}L( hP(DTҥKukm .pG[ 000LU\[[˻I+da<0fǟ!mhj5էe!2ݸc6vXo r!Ȃ$ɽ{Yw98> ,BO-|_'}y7?}ۿmMs7YXDDF{S(ڒ8fjMHv<<4GM67KD.C5I $aIc&^1vhY-\A]GU$bpd"\'0z2IÑX.lKӆ٤ZP((llP*YzZtv` B]@5TU;$YQ$MJFRõZ8v nc#xN@dCwIV7jKc$B(mV+,l6Z [rVqii5*#I8|0ǎX̡rkEħ$W z]NrblmDOE1eS`&а}Qp=߸u=t% !y : d"2IТQ,`wUY Ȫy˫%6mMRK戴hYQSרUj5:f4ùV6[Ň#;VHMӂ0cTUCS$YnPeU0]t&a%x$!Ud=O7)]((0Ij?tGAUDz3wIQf: FrFKb!j*l Ӧ^oP,Y_[#SuQFF+|UwtLBhvTănNr>j{x?z-.Fǻ\t7"GeUn | -f~!+].1PJD(.*`*PLt"!$Z+P%jr04cZ.x`bwnn?GBQE)aEm'$3dCWe U,.l8VC1N% .fĪ7<,q{ƿyb$B*G3ЍjrsWJI.u`LFZ6PAdHRH`Ȣԕv{Zec$2 /tҚpޮ'lFztvn/spxX+ n t=\4][@W& UȐV_JX@N7Ň% $ĖeuT*IR0ػsBQjN1e\nޤՖGⰔRC.d1> < 9*CeIx!]R|됺sjݦ6(("zJt@ِ$'iLЕx J0(() y 7~h>c8FL#i$C@RdY3lmS/i(IPV,6zLĈ'D<F{2vD~1wlzauB$IH$%Jw7VY۬# pdja^n6oE\{6nN|#-֞ sR q'$ TԟT/N)OKL?Uy륚Ȑ%,U/HFCNN2ޟf?M"SoZ145\_Ȅ<[vTVQ؛nOU1tYeg q5㲮Vyw[j:x>mV@rEBQU$YD3 D\MkȲk(е9i H(ئ?[m(U\/'OO5[\|`wQQuK%^<T $E7]d6%QUFF,AF{.=m#i? {gFz |.^AU$ M:uu#~;c+)Hg$7<(Q]m8~˒s$UERAueAl?p=Aܲ({2[[DY8E`ͅ$) g۔kM7]ABvs_#~wiLͮ/ysl|:x*u;N(gS_8:n KSOX)΃9n ) X$DQj'4Ã,xXKaZ1BZ"1ƦKDI" IzcjI
mS{yp=#C)/ ]uY\ldEIf2Ȫmz~x[Drsre[ ;KrIԛc%ڰx*qJ|Ƈ7f=ʫvcوŹ5ܚFV.ٛyԋ|OH8 Y_S_Ip[껮xOA|.P3m!Ο ]Y޿6ݢG\G cU^u$j"Q <L.2G2BNgx ~um|C72, pxG8ՔcS/[mKeE!Cqvj, @P'Ȋu=ߦUї.%'D{$11c~!yzaY ϗwyqPuµܟ]n yi_w_f$ "rq0%|/7*@*YQ.xC7B7ޛvі%L``CYm_1u$'GJ"uBl./KcTY©TcsFAFysP]Q]s;Lw]ݛk g@FD2 C#5Us=Q]F'$HȵUwnz$By2"2CIDATZ!9uY,Lqs,ZҼqz*>FHsl:TJL8!h3%M#r©4,w{DzHԕRm_Ark 'G6}e)Wҽͮa;.r>Gò9rdŒjE2}&tjvXl~jܵ/K0L}hz4*LO/eA>qTh'ZFuC'5]ouW$,J$4\dywi:Ns9FlPMT~ LjPɶjO\WHQT@*(=2TA` |Xh\$`73͗5rNTYc$"F$r%!A ^ܵNÙ8(keꦍ,I!$Xn@`Vh3̬Ux8H|a z[ #y o__Pj'6chx-.t<>;G#EMGO8AUmJ}sJ.a*(/{/# 2Q!}vI m ? $LVi,skz,:of%tetI>džGw)TL.O %FM (h]әRRR x}}Yi#Ziy %8=6oNMGcʜ-K,j]6!(ld](\ӤiDK I}urAD H4JYoTJS[!Ȳ fsYqV!mXcv7kl+u?敊+Em6st(w/ WS4L{Ò$J&&b!pP @A#>dERIp]G JI\,Z Op&J\[L-[ ӑ4}CDNs9ܚUfVBXo'Mg %ihȡK?4Ï~}ZltC$eQ<|xH_v#\9i)I^(N }Rt=8jMgQCVT"}}Σf|bmMı30)JqkJsh? k%>3,IL.6r! wԵ,liFU !BB`ՒY)P k2qIz.Ux԰eTYŮ(4JEV5>2b* ܞZ zQASū繭\$,M"ŚLz..aނ߭Dx"w=D,n2~6l3e6bjyzZzI`h*.  z;K*YQ&d>xeOF7$$AjR48GS ]sj,D=J@d^&$}LNqmre 5͒ ٽOu g2B2PtGط^8tZ6OŹ6/.?)^={w.?`VTi(Tlk&+mbP2mȚTbvׁ0^IE  mgURf\KbIԒ0pyK:ް!*RB2?q(@:#Rаl$0m4Ua|x=%?+JgkI0"B@ hr.j66.OpDZjDWFz(*G|! d5M/M+j6,q|0_pU71J^$:^ j 6Ba |C Qc:R!zu"m++JzPࢢi݅⁩]Zbr1j=X$ÃP&’$1Te[jhf[$U~/*ܟϒ/7a;($P8H0-szov+1m7xp7q~5p@, 9qh,zU~W'D㍳B2mX&w [PplC#4dME7B<\̳-7:9?N L6G6zvM#';e_t7fV`2&PnP2DdcRJ"svaCԑ ]e1[fXE$L!3ڟо*VܚZq<*eH;X8$4!XݖN q],Jbn( 99a(@\8u(C*fZnvo._\a>_$ƇyH+lt|Mh}!r,nSH5 lh$'yFSGGMgnAm#hD6&ΓLEfRT3ǧFG ƇSdj# spNf2>W#o%_aPABq=NE yֹ 4R ^`\2/ ISO'Dik7%n/޵YLCBB`Y~Ӽzz3Mjj6(2c# &WMTYձ4?xqL%iTC!< Mf1m^#cMHs_99±AHq{SȠf#efm9^6%yEClL:-Z=Bυ)$96&50ދ̯?}Lۡ/P_beܝiKb;G4w]frkrɲ da\ϧP+-ױlETyÏ%eYUW|GY&4sz7 r?N$mAG@a%7BT V|q:ݫoP_t:4X,D_HI`L+ 3E\' k'JStM|ءĶ!I|kj)&{O2X*;XQd>1ͽ5, d¨R3[-r.Kj2:@S4)sU03e޼>̡d;LN9AC:lMJmXx|ǡǷyI&V8>;8ʹl@$A4, 2"Pg,|  S6XΕ}\Α񰱭RB7V6XS 9QR7iTn;.Ūٱ"a#q5QJ: '>d.HB|ӣi1y@wevIQzĸ"]u}4E3 EUqu<`\E޹2hrѾѾ(E#[ 48 50K&C?jJyiZܚ\H Zb;{4п l03J%5!Xdg$Y/afHaѰJ*DD}RD8ٱ}>mӺ~P6k¤/bR$μ,K\|̇7fZk^KuMllqaK2]bv(&aD u b2afK,CI.|14cv. -$ V":/q0F2d¼ʹ]_'4z`j-y4 foƐ!L)2xHD YnT]%޽2Cf$ i'IAiEY&2jŢ\dȪR a.#I2)* [Y޻ĕU)|S| dUjt)B!|J5N#7B̕ҍuiyjAq,w9r{z+\@lͿqPwFA,L * baXX.N8ڟ@UeʸGBJ$dhښ7\[|pck]c#iNu]{}>$!~c6!4 Ѱ.$HFũ3e>1# |0'Ro`E&YS L:wfڽ\x0Ɲ><Hw^N(&`>$?Dۜ`Dk@o8`'cv.OI^ 97׹=B.灟ׁCavq>|b ! ҟq3 q<%ͮ1X`f5>3|nCy-INʎ6$0> .I0N~$`sxvPPsfS]L>ɝ2 dEQY)T9Ѷv)TtwnW$j||Z0z|륱.Zf;HGvn) ""r,QOYy q=02fJAe7?}̊@b:N ky>,zeY~[g99Hy%ܩB:=[9rzq5 YBHڽH;P3]C]D3tL%޺8͝"{Egۍk;U$}Ϗ֏5ffJBHWID炖8q(C4i \m"$zf3Gֽk>D(C6+u>b9$YSṳP_k6(,>@t3#IJFh4BJܾ/`".oc?={ɏݒm1(ح]ǁufrv͙M! Fm;ܝ]͋||crM?k ]3%rqxH"Ѱr`rHh"yjMHp|$)T6 $ >? $jB7>0>әB6dV\ζ*lh|1$лd\?Z=.̪[b(m-cqd8/+-ʱ֩2at] H*j8<ڪX?S?〢EBawPG{ڦyZ(Z_\/ﮰRS[?A$یmձ#M?AׇQe ^jrqIB;HHgl(ũ>642q^?;7^0:" '(Y ܱa^}a;WN2 #{6뀄jH ¼I%ى{{gm #eR|>9;ZN\xIf ڱ 8 v,neVKL2j<Űq/Ω#}ŀ|q0GRs7$J]$әIGvqwz{skPe^ZΕa88}d@OPnB8 ΕFZ@/Y ,d{!ȽNC,"!eQ71㧟Ormbe; wFQm}*v) ZF$hՆJH,uU!di4&wgW\aPes1Brجd [=ޑT<ՇmbhN) bdMHYl76r6u/,"]UCGbzۗl"GngD"rh[rV.Wπ~`lnϩlq'$$na yf-pGpTH()7ޞk#&@@oMBn&Sm z0wrfjk"1n `WX*Z.B OfVHd@nNe-6J`#jKyrZ[g$p:,Υs.sqlKk# p~I?^ཷv+ʹQEA `T,o_|n+Wmk66;vc3?J-VE]}L%t(E2KgLtkwxEIj6 ys_Yt<||N|h8)bWoҤ7n6¼"{8ĭѦnq|u&si_]"_? {rx"pD^B$C<b9-JDaq}b ' ^.]4p}[y>+LO=r Y3,f>C)~QaҾ̯ljB-ey鍢 wYmF"ǁN &a$XdEAY-T%~yklm!x?CPH6k:#ՏQs'[lN[W(T JX]5;3mpI&S9nNqcEa&x~P)qݗK`7-/[Γ6YGoܮ{d`ouEwxI/Fl3>mƾ4\;vNb=ϥlQʐ&Ω(oa*uNM:FN"3Cq*4banďɻ8JN{zf, q=ƛOٝyͶ~2y*1CsdȌ}U GvJ)*}IWdÆKc| g`[Hs/|s[Gg'; jV.1@߼M|ϯуUJ[+CS@#†Pttg|FYzH4ء~:rZ,|r~,>?N2m0?/+ޔigܳ-l>yX``JFY8V;mަ,k3sqlu/NL'n30:m@Y;P`jg[؍xOrd(E*H_t GS|>uuVڎ@~so\]9ຬM>{XX@V8?fl1gl٦sMLey$7&W1mw_d~_ӽlF$R"5؍:1:ǩ`>C" GڣAzK$UüvrْrJRn8Si1f;;T!p[4[7pDZc~S=-&[,/NwI 0Y޺4ͭ"-x˻,:e~K~So"[9ma]ᕲ(H#Fleڜ[@^ u|tZ7NQ68[Tipn(@Bmj6-.y$\T3rmړoMfKl1-sgm9(?ʂYRoHR"R7m>(1`827)[E4q# mf9Kk%~ug_\d1Wi2%xO}7c 0=f^ĵ,1iz@ { ֖s ^).eCɱ2[%N鋡xNNU}iz7oIfeLˎ[ET``SفǓ-$+[z ߱iǒh~VaPn|>Up IQ4+SoX|s,BGQ|xo]fz}26lqq>޽l1WfvESSw>&RjtM״Mƒt}gBq}(2j e\0 AYuЍ o_bko{S#ۯx*7'e5iEk>,s?΅#LOI]>LL0%GcidUw]f $˄Sixf$vGYŘ,zkS9das!]}Zz.:|瓇kL,p]o;.uCD_mӶm9;Wf4j~ŗ2\5[Xm[ԆI|HVg[dK 8p e"jspJHץް:!W,Ұdg33$ۯR'0<DzŦ]%]Ǝqន]'[\WL>,k 0Ʉ?$`'bUUt 9޽(T4 p}0>‰aȁqF{.VdxRcfJ.W&,ܢ?|u#h "f}$5__*'cq3rŃ}t$#u`܌(Gy X|1 jH (ݨlkJ(L8:[+&TCJ P#-\!JF@TL%* k/ vڿ[p;zlqi-m$;$ ,]J:,&VKGSMT>n_.TJ9,W9Wue1_vMZH&΅Ì P=2%D?7 G8"HpyR0Z/3IDP$HxNȓjx$} A6x$eN 3[٢$LgglI %0s6@z(hALͭDe̽_*~A OB"HchH IrHDH W|p{w2e m%W1֕\ a^9>ĩ> ]vYDjZ.'(h oeJ#W` @<-6PH:#G@XY>}tsd~O{$DVo!ǿvs=5^9>D2X"?DTO\nYـdX-)?\n@)Y~qOû ]P_-8lŃ ![٢Ϟ6e~| q8H0lqq {F X[D C9 y8HHdM?B̂Y~bs : h ?@A?gn/$?Y%tEXtdate:create2018-06-06T08:50:26-05:00QE%tEXtdate:modify2017-11-21T00:25:55-06:00IENDB`forcats/man/figures/README-unordered-plot-1.png0000644000176200001440000006654114004267477020723 0ustar liggesusersPNG  IHDRz4iCCPkCGColorSpaceGenericRGB8U]hU>sg#$Sl4t? % V46nI6"dΘ83OEP|1Ŀ (>/ % (>P苦;3ie|{g蹪X-2s=+WQ+]L6O w[C{_F qb Uvz?Zb1@/zcs>~if,ӈUSjF 1_Mjbuݠpamhmçϙ>a\+5%QKFkm}ۖ?ޚD\!~6,-7SثŜvķ5Z;[rmS5{yDyH}r9|-ăFAJjI.[/]mK 7KRDrYQO-Q||6 (0 MXd(@h2_f<:”_δ*d>e\c?~,7?& ك^2Iq2"y@g|U\ 8eXIfMM*i_@IDATxxU7$FR(*kgAWa]׆"RemOeaU,JYq)*",EI )߳܄Lryig|眙) @@ RAa7  PN@@  Pnv  @9  P@@@9@@*T BJHMMӧOޙPZ5ѻo39622dSYl~UV c,j]gggw!W:###dэ1*U933|~ayVZ111 * W^T@uC5!!iiiSJثAko[9**JK-I˫M/bK5rYunGGGY?m"m[=Zj/9FU@|ʯ@JԪꦰ  @ 0R`_v>}7F4$B@W4|떒! !)@A! +@uK@@ j@@ ߺd  @H dpP  @ Y/SNɑ#GdժUAnj  @ 3ˉ'd޽2sbb6  @IVriyd߾}rA;v,Ǐ\:ɓUR,G@VGqN2EeذabgϞ-iii2d9rdgg͛ĉ%""@uyJJh٬Y3yer=ȥ^*͓YfɢEL>ÇQFIVL;v쐵kСԩS7ƛ*U%y"`@\\\H522RB߿X_ mg'ވ-{8'+뮻N|I_d0a|ҢE  رceӦMryh|F䥗^2A?,֭nݺɚ5kL_KjDͤ$:f˟x _SN |I @( PKxLn%$$zz(iodeںuk?m oM6W_}Xi0I?b͛7c=foz?X,< :t_}ղ~zݻ_7t 8Й4}nqՍc&O\?J[:BѶ$mU:tHĖd[=kLR^=9zdffz Kae5˖-3^;J۶m}Ӂmj ?Tvvkb iӦo^t`SwN׊39o@@0v0J~zj+L[lbgjcCb]_t~׀S[Ku;M]viӦ .Nnݚ/-6c  a,`m veX˪U 5VoQj֬iനs++WʠALg=fU}q:To,*O! .m½ŕO/2ҀsVIOO7_&-bbbL0INNv6M:to߾e @>ӧ目 2ϸՆ⒕-ڭ>|TN:)gƉʜ  V2biyA@@ @֭+_kd  PWO@@7@%o@@BH    PHʋ )X8CoCbM>222)sbb[֖z7-Io;p-E A%R@@K^-@àRe }ଈ  :1;@@ =  @@P # .@:1;@@ =  @@PoڴIo^hcǎɊ+|333}y  _4GO?TBhrJ3ݺu?:@@g%77L>}ZRSS}ɓ'%++7&{9?lw-@޵kdgg;xE@Q?Wѣ{K/T͛'f͒EIDD >\Fe\jhKhNNoaQm|6)))]ne'ݻw^|&-Zd_[7Z%&M2s222d˖-u9ߘQm)͔f&oP MC)Js7222pǫպU(m^[?::Zbcceo|||Ng%٭=lp1/m-5k.P"YYfѺ^ަMi߾FhꇽDn.Ӏŭ"{qVЀVU7SE]q/d֭Ҷm۠K/IӫW/gmڽ{ʻk :SVD@Hԯ2^B$ $7o.ڵ3~|_JرcM3A̸aÆOB@l>deΠ:>Gn8z%Kw{b:uo߾gP’7>}z+U111fo6uq%-I˫]vQ 9l9p@5_"PkyB腮 ޶z.zѣG}|*UXv9[i-N 3x dS@@ l@æ*)  PoG hT%A@!@z(@@   7@QO%  6<3lt?ypbm@@h=sCr@@(h)X@@?sCO0`OwEt=N"ξ@pSP7u@@h!f  )@.y#  -D @@7@%o@@BH    PH 3@@.ݼyl߾MSF@ `ݓ/_.5jԐ-Z`a  [n=ydffl%++K%--MrrrdݢJr1~JJY?ӧeϞ=f]]ө ǃ>_&A@,t ɓA2x`SU&L/\>ly饗D̄ٱc<Ҿ}{_gyFT"ƍ;S.B|j裲~y/8VX!}tMddن]jt$""B^TWVZ(׿DgΜ)1112w\yd̘1RNٶm4lP=*ׯ7_H=@ǡ+? f2z|zr挰NY8y}]Zg6:ez=ta֯_Z7 6[4niӦO]еkW\[P.##C%޽{ː!Cdȑҽ{wYf{&\zi!T8t?NJNN6i7^5p&,3D[^ԁ7666luD[Klg$ʬ &tx-ɶz7tC/ַǀjO:+^hT\Сhs=өꇸou5=:T$VN @׮]+^z]v|&q8y $T[x4Ӥ-Lj֬ϴh|teW_}xbiݺ @[liƌjڮ];3 p5@%! t^kZ2o6L^pKXmqz!xյO>BڵkKE/vҤyt\8/3gϞa@@g:zDLz5 wcڒ]n& ."ox@P=lI6=p-li@g C = J^z1+ƀS[@?iѢ5cǎM6I֭g5נpŹ߹sg뮻LyM7W\oyql2yZj… eMk?~oZh j֬"XOڶdc=X5jvjz.BEڠA[)3ߔygwռ.3>48ܺu$$$^Zu |дr 7[N8!w&]yS+gv{' :%%&&/99ٖ"Z?SSS)ϣXSf-hRRVZrСRyĶz^+M=zdffz+ aرmWhpqc5I_I ǃ:]S߿ѼuI%5Y; xU CݻielժiFfϞ-~wիMiԹpHF0df͚[UD"#MNW^6Ǣ2O] &-+o4F#--O [5?O2o<|#rh1c|7za/<[l)Iǭ 4Hnfiܸiu1$@@f߉ݣ:zk&@ 8ѣGn)Ӯ~J| 8}QzLS7VQn&ڷo_7w!ӧOw5fҊys}ԿSƀzJsԶ d hinc@urq)Z@?oM|-#s;?Œ/   @ mZ H  #v!U {A@(hY@@Lebc#@@ U@@$@Z&66B@(WU͟?D=^$@<"@ G*D@E4\jr   #Uއ9`ΒBP`ѢE!xT ~P~@@@+!  ~P~@@@+!  ~P~@@@+!  ~P~@@@+|߾}v #B@BOd˖-p #B@BO urIʒQMsNIOO/ѣGȑ#3@QGq֧L"{m۶UW]%ݻwzJ5k&[nx@cr~M{\\O:uQY ^#$K6ONY3ƔcVzm*SV(~ᇒ'<?^ڷo/کu]'_|lܸQ̙#cۂ ̶΂SJϞ=I^8#UJ(/n\zu/lc֭{F7XUY{%@:m| =~ 2/^,K,1[͛E|jPA.]s?,_ 6d?g7=C9o"ʇXVJVdddkYttHJJJ(f(wZFEE~v8qBrss+H*v׶ճ|&&&|OXrޛӚ[\ɔ0?66ַ~0WUSM v;YLk~yr)gҕxW%TnOTj Ԧ2ky5zVfI\i-ɶzֿg @uh 2WVC@Wrۻ[|I={4hԮ]p 2doM6-  m2?o /P͛'ǎ5MMǹ@EZ@CV8&@@ @ør)  tbT1 0սL>@+@ w#G@<)@j@@ z8r@@6@w#G@<)@j@@ z8r@@6@͛esf@33-[._\3 " %8KlȐjժɁQFR7!:w^[977WRRR$!!A/ @B(j^0Af dǎ+H&MdڴiRF K䥗^ 05u~ii߾/w]3Ϙuܸq+V~7vMdd˳VZ+{WهRa/9)M-uժUMH=TZz~Tf=5%&&W[~VNj,QTC Oxyp2c iSйpB4iԱ4mTf͚%-yyy2qDѣGZP5gN])u?e.uy^ ~6 @U˦rX^^Z%ƍSWڵkoSg6l-;wS%YأG'%''˱cǜIW^ԩJ]}>&&Ƭ)lIRVnkyu(Ljj D[Klg$ʬ ø ƶzA_Ifff9kVlvzJ\HeN2-Nv:t #F{t@@@e7k~Ү] ef͚I~Lˌvϓ@@'4nW.?|[_E3F &ݻw͛_)@@ *Z:LZ9pޚDϞ=E4pZx  tRlƪ  ~~E+ޢ1@@ %lo(_,F@(A # hz  @ %@@|@ד@@J>%g k( -[7  aY @]Cn\=?#ӧ{P9N@ lh   7@QO%  6aS@7ꉣD@F4l   F=q  @MUR@@A(G  A\p,Z( ! @PSdǎVӧO˞={$;;W3'O,}9rķn&999{nIOO-7N޺ĉ[~qٵk/   (XyeѲo>iѢ<'թSGZnL믿.V5kÇeҤIҬY32e Jm&W]u4mTf̘amٲEz)FN^z%'$$駟ʕ+^0h`z3gԨQC&O,}4j_s9gsNYnoK.ڵkxF䉀'?˼XUz9JkPiQQwƠVhR%6pVNYiPnSOIJJ<o+s-4?Tfh|r9s{'cƌ1~~'W_ eРA2rHw1AY̐.H}YyפUVf?Ǐ7;vL-[&TVc…2|pڵkY_gN:U7o[pW@C r.l,6lؖlxW0JA߭쟩^(߼ytz\{!C˶mۊFMK[yWXaT 8ڽ~&7 6`t?ljWVM>ٟλ$ͤ-$on;?*ўRRR|[ժUK:dRnY[=ի'GLOWqqqŖ!T?t,ٳE5k׮\~往ؽTu.s0ţ8NוCnݺIN[n:@7@(_[Q5 X5xծw89&gW@@ `qF97k믿޴2e]&_}ŋ͘Ղ aZ.]N-ť:K6l(K.5-XRܫW/ٺu}ҦMٻwd>  A7AuV=modf̤32˹O>2x`sOe„ U5hVP]I&f,?Ph]:FT/qMM:o6]9vXMy X'S )v18Gm=^dɒ|CqBƵ]KJZ^ uBII*kt}POW_Р 4  A[8Jfi0-?Eǂ^yhtƍg"hK^E뭷-+"  (zCnA:v(zU>H+׹OmxNySo?$@@A#jSU/6, "  @n*oJ_    @6KE]xT0ke˖g3  @!m&˒R? g9  @  @K-hQB ̟?]v#ȧ~Zy%`  * g{f8X@@ L @y|>B@*A TK ի'jՒ뮻Nڷoo+%  Y/Brl2ٺuΓ_מ-<  PA-?ȑ#GLw)r˒]G@@<)t:bٽ{tT6+ȟgYh' A# T@PhVV,YDf͚%-[4GW|cٳ+yK.r5vzjժ3B@,*{~>}ZWĉrB67}Ԩi޽2sL7wA  @ VZUz-cǎ 71\s3:U[* & {ћ;Icǎ5333eΝ:+  &}s9GjԨ!-a.Dҧ!C4ij׮]r<`qs DoEu&/7%%Ŵ/\Pm&O=4k1@ӧODڲrrrD[I/zw~*_b3b{̡QnmiӹՆz:~E7|#: /??Hrrm7Kow.7xwgzEǻxX @5Ԕ*{$!!Af̘!Ǐ7HՖS @EueSN={:V@+qp)GiDW^b]2׭[7,zNJJ* QHc\tn_QC~%\bI&-zQR[o9seӦM˝-z!W_-_~߸q,^7ov6کS'y|6lXT9K182gfʴ7Ϩjժ/Y9::ܗY{alJz~.@   ?tPӺy!iܸOnq3@@|A5k֘'魈7Y衇䣏>rf  @@I &}ƹ32CW@Mh}&} @*W P}^`4bYv9bm={r5Tn);  gjsoرy_.hJ}F=S`@@r@4h W6D[E/bSE`e0`@Y6 zӧ.+" ]A'N0Bٳ @@5T3nٲtMm@@{ϴ|ҨQ#5j$@@J#tڣG_j/>K/:믿n-}J̺  @bcc͕Ǐ}7|#G ʣ>jw@@ @{y'EҵkWٽ{̙3G;&+V w4  @W[/_.[wrgc>6m   @/ySNM |ӼA@@@]ӟ䢋.2]O?_Knn/ƍKڵ}fr)9r䈹8  )tWkw)>}>^2_BBرCt@ 3C711FJ͞=C #GXZ;jw_JJ)7{̅Y͓YfɢEL9tĿUV&+{3|7Å7.?ˤ3*y)F̖TjUs΅Z]_G?OlIιmS=kmS֤Ėd[=;Zzu_S\T ~_T> (jGڧ]$kyQɓ'VT^o[oi=xz ޣ 4so.O<[o5^Q̻dٲeΤ,YDtާ~Z}+ny}*Դi#rnL8jժ899N5V?G@lgBٶf+@@ʴr4Ǧroرc=^ 0kԨkj~NjРԭ[Lji„ U?3mܸQB 5i< ~ҴiS3_lذ/ecc?r_XM34Hի|F<NpWͷ3z)$ Rn:u긙2111fnDP 7A%B?6ճkMeZj7fK1J_i/;rs6P * ZٱcGjw嗛qV..]E "TKTo۶|c۷kK?Ca Kx㴂je_{ۿo7E[{e6mژB8p_E@ ^Yr&.s HQ/@r wYg@qҥfl |]כoٲŴj-z~i;:T^-â-E%m/L Jq/j{;ҀS[k4iKvX .UձY_  eAW,e^أMpHhLi7(5k4Npxw˓O>iR|РA枣/oZ/j``ҖYH8kW@/N_y啢Xh0ܣGіYM7"iwKYTB@,iоi}n]>Srj@[Tҋ4P+j ]vڵk妛n*j7f;wη<71̞i[oӤCt8inf_mZ\/@=~n:T{lJ tƀK z8I{y=c@᭸T58߹IO;(6RnN~ڭ?|T-h8  @pzƍ3W}?G">C,Z:-:. -@@LBPӋoB_frl  P&/Sl  @ L" +@/#  -$  rE mRRRʲ)  g$@ 1  @i@K+  g$@ywz(NW K  P*Z@K  g*@zl  P*Rq2   # JT\  pg*   -+#  ŋԩS۷O֮][h>3@@@]_]N8Q(-[… g  `h}iٳg2//Ϸ,;;7Gʑ#G f@RGqP+W^xA5k&r3gԨQCsժURfM9|L4ɬ?oDԩXv%ׯͻ⋥vھi7DDDmyd2ٹsiSS׮]Zj͛ʹw2d9rYtgiҥK(m&M`+p =f222JgOLL4ɞ-CiiLMM-]_Q%$$ $ǎ+ÖD[jժ%2Ym8YzBY-.18F:S :SSݺu}uZ[KGO'it83=# "K.%*ruYҰaCYtEF \X(IDAT,.L+7pR֭:S+u>@@o _Bi^H4k,ӧY[[-uN<\4Tzu0aB4L׼6E7m4r&@@@ԺvرCz-ӲyA>}ˡCR,'}[\TƷ*Uo@@?P?o֭R]/DO;[ 8O";΅K4  %qDx߽{=%lb@@ptl۶)aU# !UA   @ %9! !@  hY  @\R82|III ǢQ&@qZ@C8<@@ @íF)  txux p+k> %@ hQ*C@pM5Z2F@(J(! &@-# %@Z @@\ u@@ -Jy   vڵo߾Rl!yfپ}{ae@@ @KQ ,o[,_\Rm  @8 Q{Bk:uJv!G-;ydeeɏ?(پ&77W;Vh~@@\GqG< ,ժUh"1c4kLl"={QFɔ)SdϞ=m6ꪫ$22l3<#UTq UV'zΤg_C z\nTq#PӦzv2;jߴMSV4go!ݻwORRRy~z^^xW_}U4h Aȑ#Mn999yĉ%::ZFmPg͓;2uTfxM=zw6Eï"K(lc֭[™~m礤$WJteS[55%&&\`7 $WX!s5iyim۶Ztt6mZSWرth~L`:k֬{d  {\0-ڂ֢E vƍW^TD4ibƂMcƌaÆq͛7/v]  ,@v+_Tnkmw^ɮl*wf-[:WI5ŋ;" V Qz^AB@(/Mzێ@@(h@@ec;@@2 @@*@ZV9C@(h@@܆rn=;U# 6MUR@@ި'@æ*KWnF@>}zJ@KԮ  @ Vzp  ]v7E@*]ҫ@@ )-  P^  `]Mi@@J6ݴi|^  `'|"_}mMy@@J6u;&s&%;;[%%%E?iٳgY3u:55շɓm54ɑݻw|}+@Tg/_\-Z$Rvm4il۶M^}U|FEEɜ9s7ސUVI͚5f86lپJ*2biѢ<裲~y^zIrss%!!Av!O?ow\Rf̘᛾u־i7hyI  `@RRF@TYfÇ>@Zj%;ws皠TO TgΜ)111f{'cƌ:uꘀaÆrQY~/GwޑM}i! (`uڽ{wVNM]t-[ARn]3ҵkW|޽{ː!CdȑۯYF=\p^ڴjh_ >}ƍeÆ ֗z)dan& I  `qFGGĵz |:Io6jL:M =%j+k׮K/_]vɅ^h6Q)  ? Yȡ-zЩSDGH.3W;/^lhjڲeK9x @۵kg~mС P}dfLhe„ fԩH/JKXТ|2 X,S;]2:j+B]n& .@BT`UVTUUf~yAժUEH  g&`3ck@@Em@@,@Zf:6D@(hY@@ecC@@Em@@,`}@,҆uPiJJKlcbbA\mI(sʖG馦Rds㄄9p5eւ&%%: SСCcCMmg}bzCm^N9[\h-N  J   X$`}\-bE<9 &@ kd  PhQ*C@pM5Z2F@(J(! &@-# %@Z @@\ u@@di& ȑ#jժB  : @?ꫯ )ݻWfΜYh>3@@BGw1ٷo3ɓ雗.YYYi]sN%% l5SNLIIl}=zԴ꺚rssE?<.eG@l8/_.-H]L4)_}M (uYBB>|G߿ 2D7o.}hsΕJbb|KN;^zɬyw}2zh9uRv%|y." DDDk,cccϨ䩪U#WrQ}*UHՅ]xrTfܶzvny)&&4n ~Vhs{Wں8k,SAÇ>@~_W|g̘!Ǐ뮻N bkҳgO`ZJ >?{/xy뭷~fϞ-K,nݺUW]%K.{״j|k֬1ԩS}3ϋ5ka1XOڶdc=WVͶj5jXWfYc '7rx6FإKٲeKPvoܸQ/^lDIMM͛7 4@tM7yoʹ ;v4__| Z%[o9sE/jҤYMۑ#G=cy:ׁo~<pߴovJ{mR5^Fve>^і2 L/ؔ4>~5E VZ7.''ǚrV{Yg{^~><j%9I+QFΤTo:I)jzÆ M:]'Np6+OZ~<Ӧ_ʶmnkڴԩSt2e_~F u:##C[y1aqeu~?󴩞z̎Dx7mӹՆz%_|aj`tA[t|&mڶmy$mڴ1Z^=8q n3SwjШ}Im(K[<;_Ǜwy_ TOs@@<j 4HZj%-ZWGn6;v\pw} 1bɣn~mnvY` .[+ jf9眓_צk`=  M?5f_iU:}c>ճhi0Y~}뮻sEe'zk& ^b&c+% ZE3:4}t7/uE):dPCcoΖzPw~͝u=tPX Ҷz3wP-=;T \I]qnh.S]B۵kL`M73-X n4  @ݮ=z7l`P >ݷ^ܤ&;MX@kqƢ?eMZL˚'! ^EH^F@@@m}ʎ Th%K@@fPk#  EH ?oi( ǀ v jW}SZ@@@+ 8@@.o_i {@N 5QZ^pD  @X uR8@@ @CN8"@@ @úz)  zW'  a]@=Ы@kwҥrBk9rDVZUh>3@@ 7xC?^h{̙3 g  @`>p\߬cǎ `w%3 (@D?S2qD4h̚5v>|ɑ~ɓ'ː!CdҤIr7|@6ߊL  a"Ν;]we̛nI іe˖/ժU?P.\(ÇmƏ:u7@>Up{E]?OPb_vefIݺuyuVIHH(f_fEJQQQSjK-[bd„ 6lXS z Y  `@Qׅ.O.l+%')nͯR嗑 ҨQBA+]ğg߿_n6kLIr)gҕxW%S@]ohx9EGG<_"ٽpɒ%"۷ԨQ\dW^/&˴js}6mD/dzw}z" 6 DmٳGn9qℌ3~u^zge (7S:u̞@ܨ"ܥ~&[6`h\JJRlmS=kKwz$55z tq,JVNy2tP3SNOnɓ':Ȉ#˷oc   U={DoI|Ita.]Ȇ b6m^r/گ_?Yfg{@@:s1c5]"$Ըqchj+zm%[8il2>ޖRN#Z@è2)   P/Lj hU&EA@ PK|7xjJ&LP9]( u]h K-wqyw}'mSdKuϛ7O^x}/, .,yEzXI(?syWСCo[J#GdZ{4lPlM E'>mVn&6lGUfBuҨQ#i*~?~$''+ֹ'ߗ*UȜ9sd֬Y%yOz֒l߾]gdzdd>|Xf̘afocǎKFf ~2ZՔ RY4ŋcěG8~ ^+_^7v%cƌp8 >,_G]vmIOOwe~rCRS: ݄DՅL-J?UA ͕"MDigmQ.Z(n5c%A QQAqrV QK{r;8sj{{~35Ϝ{sC:I ]OLL ;e`XC-tCEٳ;w94?Gj^ʒ^S~bbB͟#U@˜3L8Q233<:D+3-./vϛ,CѣGrBNNH[+Y?zNAk6\kkk&~eedX-߷{MmMvv/mmmfWE3huV8k` :;::իWf|: @C;?64Y ͒f n͘d3n3[Lj@@o=/ 8Sԙ;F@&@7z^@p3wZ Mo0 :  pq, 0)((pXi.IR 333涾AD @z ȼ p޽JqqѷouNn߾-244dڒJYXX---m:Nd?}$z|/_]+ 7hQ۷o֭[&H,)))--5gazzer NH:;;y외z/qݦwY/,,4eQj񒔔$.]2?@o¼= {I{{9 0޽+sss Y__ϟ?{yUӛYQQq?~lʧH^^~dee)=rDz Yߗߛ:XT\|Z5@լ>X}y]&99٬onnXA+@z\AGNI@ }gBBy׭EYkqϝkyx+@@? DFFq:γL4Aڵk2880q3A,..ZGz 9R9 ! @3&Y---2<<,T&)UUUf|fss :11!O>5 I.\/$ϟU cbbxЏ?ϟ?: %@jI@ccJL(y|d\.ɓ''Z&--MiFfGGGKFFhR7KNN&'MMMys(e@[ q= 7 pExsu^rEwullƋZc@]؊  #.j@@< zva+  @}K  @=@@G>Z@@]؊  #PR-  gP.lE@o4SPIENDB`forcats/man/figures/README-ordered-plot-1.png0000644000176200001440000006646314004267500020346 0ustar liggesusersPNG  IHDRz4iCCPkCGColorSpaceGenericRGB8U]hU>sg#$Sl4t? % V46nI6"dΘ83OEP|1Ŀ (>/ % (>P苦;3ie|{g蹪X-2s=+WQ+]L6O w[C{_F qb Uvz?Zb1@/zcs>~if,ӈUSjF 1_Mjbuݠpamhmçϙ>a\+5%QKFkm}ۖ?ޚD\!~6,-7SثŜvķ5Z;[rmS5{yDyH}r9|-ăFAJjI.[/]mK 7KRDrYQO-Q||6 (0 MXd(@h2_f<:”_δ*d>e\c?~,7?& ك^2Iq2"y@g|U\ 8eXIfMM*i_@IDATx xT7d! ! Qe;U\"T-*U֢"Eˢ"RAR@يBHYd$$s|$3ssIsν7$$@@*HJ   `@y#  Thrs0@@P  *@Z @@  @ T8XYYYrR; DKott2///Ym~%gΜ 2`Z_m`gi}srr¶(]J:>}i8i[;kǛv~~~86IeҶV @}T &ήJVQZ%icbbDؒIII 4gbbUUYoEڶv/ ecުT@|oJ X%@jUsSY@@ZmP)%ׯ_H;s̐O  ^z@v@p+B#  uoQr@@l6  WԽmG@@W (4  ^P%G@\)@Zf۸ql߾rJHDb{hg|( @@#@;رco^={V<'Oʙ3gCiР>|lv!k׮u^Jv$--:OT Py^u/w!YnmjNα:kjgXBBЛ?B_shZyGhjܺ;w5k֘믿8f͚=-ZKӟAdÆ brIMMo]V^mO_|;f>@-ZdZMz駝2c iڴ[8&n-$ƶ& .6uNNNIIIIoB=@ڵ?^,믿^֭[gawcx嗛S4kL=gho~kK˖-'Oȑ#jժbY  _4??_&O\jꫯʱcNJ)ݻWfϞ]l9 @@ >͕'NHff'P^}̙3p1JJ\Z'edd8Oͣv-+ @]ܼyL21112c y'L-M6'JTT|g2i$iܸ>TRwu7)w)N:&>}Ȋ+Dkɇ~( 4Çˋ/(\pg O:yA)yto ׺:?l 8._\y>@-Z$C{رc=5֭[ԭ[׭ErժUv,B6u]vio[oc;׬YX3ޕ^zQjϣ &G ?SIHHUE]dw<Gf3=nݺUKUOR^Pk)''GG|'/)-:Y'\:|@8ے%::ZlBW^GrݓHwDwM$>F#gϞuuȱN۷֭[{ awSvO6E:CSʾ}:Y{ EnUu(+wHpLZPXi`l~H߫MuelWTg{֤AYlkg'mk7'=S_{={^-ZHVdܹwߙy3zjSz)uNҠQOL.]jݾ}[ڤIBV^ՅN{7e͛mH  mh\RnVӍ'M a~ڜ' 9?O3 zgyg;2j(r牞K5͛KJJY o]6lhz]uN* @Y abWbw^I ӻHj@i9YTQPYRҹ]^ٮs{C𡞧&{.A[6s̠M66 !}{ʖտS9r[SOl,KMMCY5o[;vf=z4"=+ME|6z_W67K cccEJJX%2@@ "6-KcB$@@*  Wr  P.r  @y@+~   -;! W+.\h)jP|@p=.l4 YͭG@@ 0F Fl|nYPV  @ Z@[  @ V89D@ =  PN@@@nj Ths@@@nP۟# .@z6m۷!mfJ@@ @ϡA7o\jb /( D,=sss%''GҠAR?q~+gٻwԮ][土/,11b X!@TJ3oٲE^xd֫WOv!QFK+^zI4R7nm֓?~ ^njYrJo>*_|g}(DGG"Byz]// ] ;~/Hj[Ɔ0alS;kۦ:{[SJJym촫%ud9xY$󟕻wYfIEɓeڴiԹo4nX̙#/2qDZ9Ӄ臇wPdt{pSe)?u.uyt_ _beSmSgsi'Ֆ.%5lYNdԩWhuSׯ_`8q:=q.]8)==]222!yLKK Iޙ y||LSؒD{­-Bթ0YYYd͊N߳'!)aݩS|PgD}vɰa7Cc9  `h'}fˏ>Hڴi^ݤI&ҧO3$@@fh}~g̼jժɤIث&:gԨQ2d3޴i @D4y7zƻ+ӹVNzᇝf[n?K8-YٌG@@JgvcS@@/P/<@IX  PRR6/esV# "@Z @@+@\OrC@(E V# W4  P-(RW/\S8RG@@ | ߶d  @D FdR)@@ |߶ igΜ@+@{ێ#  ueQh@@m;J RԕF@@ (9  JPW6F@+@޶  +@l%KȩSȑ#jժb3@@EE|6m?~\+g@@Jٳg3\AAʉ'$33S;fʪ',VӧOΝ;>J#;;{Bm>feeI\iw|gʫu7y N<)gΜ)@@k*V} ҤI 8p@ϟ/0N21112c y'L`AeӦMeĉ%|<&[?,z-[K/ddٱc7NڶmO.)))2dܹsM;h >|x/)39oҤI2rH+w}W̙#/6:t1BZhajݜԪUyG uJHH!ʔllپ"^pcR[[-Zo켷mm5{:8̂e[;;QUV5ܼN]|!=s2uTtXBƎ)h.X]4khS:zhٸq\z2k,G5M7dپ}[ҸqcO/yOtR0a|'>)oР '3dΝe͚5&%..5k4|jVCp ݞjԨ*DLml -6ֹz궽vNJJr};눯TLqN:)Tzv4ԤC۟~ 6l z"t|ӦMyݺuM/6l(ׯ7}jٲ)ÿ/ #11쯽_'4i壏>ef:_/֭=N.] e_Zn2g~PG{% Yz\s5&_u ީ[Ӥ= >/3WUz׾e9  !@OO{3=Etz[oճw}'}2l00`@'|y=y=:9!I;~I\{f8DrwE]dzfuۮ]w=H{8Xmڴ@@~PA(+ᇢ:A/t]wLIhh i׮]vZJ\Orҡz//t1tF-i@|P_ItP3g222r怺Uh2\ois@W* kr. S/3gH|ah0zI.\hjԡC?-p橖e  BƌcX߽{FsF|,)i|͵9Kچe  Tp9G/t7F\@@ TIH~KJ@@@jn* Th%@@ ,  PrRWPeff]k@@ 􀆜  x zk@@  8<Я_,nʒ9 I2q1   # IL\l  p*  e -#  ?  @@  *@z%d9uT5퓵k[@@&ir޼y,Zr  6 gϞ={H^^ , <{9rss=ˊ>9z9rb^# V p+R>^xA4i"'Nz=V5jÇef;,'MdEҼW˙3gӞeFEEy^I)Vײ[e?7o봯溔Թb޶im%N]mhgP?48|dԩҢE Yb;졁={˂ ߖQFyreÆ &`'|ҳy{ye3f̐nݺ9]Xn]ז= nc[TV-Қ6ֹvڥ"m۹f͚oƓ'O;wN >5uIM6|jٳ 4Hn^/ٶm[5:vX$J~{_;v:O*9u(:e–=UTl[l999ԹjժKpff5u֊H߭GRŶv֞ϔ3+7WiyjjڃCBرó~;I]$R4]xᅢ?NJOO/ zg}0}9s9"@@`O愡;̹i֬ٺaÆҽ{w ZZ5iԨ ?MG%C 1J6ms[V  ,@uu(_6ts&g% Ty͛7/E Ȓ%K<" V :d%}J?@@0   -7;" G|G۷ 4H6m*[l{rAIIINz)Сs=K/m5|8^|Z']q8Pc O,sc5X,mҶ%:W^ݶS=9pC%|3+qejcǎyP߰a,YZ,ٴi9IDMvY&}3o͓Ҧ+ho墊#V 2͜93ٗ9o怖̕;0ԕVB679znH}*Ʃ%ѤtM:Hk0WZ@+2[unz%^}%-48a|gZZYk@@ ޣ=zȨQe4y\Pf$]Zj&}E%MzbN ! Pza[n\vڢg @:԰aCџ&=͓@@7 I>zǞ>ȜxzL: @@@@5C~[Qt@v  v @%xTLϪn޼yżF@@TO[T*^𥕉  )7;ZRaXpuKI  @E @ '_`@@pԻz$ .Ç6Νf9  E@{74h`') ^/ROrɿ@NiY { _˄ LEqOScJ  Pz/J  (^e'@@ ^O@j߾ԩSGRSS妛nmF@@ ~uVsE]$/|Pv@@W Pȑ#GL=#wq˒k 5G@(@adҩS's(,^Lec@@{?s,]^zFKό%++KΝkF}\\  @ <{۷X ?.G-<\XB$@@(={ѣe޽u 7YVOOĉ:'5;;[̴]^Rϗ }ffDןI={xkuRѲ;v,r8y  B/޽{\ իW7^NN9ITI/ Shwjϗ^zI4LNN;vȸq%rNjN%3fIU^z >5|}QidժURF 9|Lusj=zҒ.׻Aiҩ 2ҥYF.Bp^jhW]ߡCyI}( u;LeG{oVؒzڒrRo}I111 %󙒒bb!usrzs}աLL*sY;ԩSS3MȓvI6m7wx?lM:\$NmtrN:U:$;v4'ji]L͛C^Wq {YǤ`fyB ^8i}oӦ:k}5EC~3 #mXnhO2iPW4 9s |萴lIZ_DZ]DzU O~[g:˦!xYGOԩc:"a^߳{@J:P  pnLT<7?F@(h@@4f6דw~Gssu]g.GtnEbo@@H8D:׉z\=Eo5?ֻ,q!!  K !M=O,Iz; @@@ @vgzq^*G?0c   s{;zѤJw]i6;Zoɦ{ﻏ!.PSZO06lm'5iܹsOp ;R@@ռO.ro܂ꫯ;eС@@l8W^ZVZ%[l͏n~X -oYX @2?~ܜԭ[7  hfܼysyyy9   oۥA2b3I  E k׮? _3ҕW^)ڵiӦYuI-  @aPgsرcEȑ#~O3myD@@@^yi֬tIv-ϗ Yr,ZȬ/z^#  ||Ϟ=eŊҲeKo+wuN>f8^qF2   PT +^:tP4k }bb5O@@(*̐qZ=y6lPjժy'˖-u:9r\?y  6P=]ySOI.]̙nx=;VtqP_ݻWfϞ< @p@cǎr!ўNM_J*2o @] ^zzjs-[^~':`5y P $֪U+set+l#  `@*i`!H r̘1f>ivTORڵeIz}'<󌙢At. *0=ӕ{=˽z&U5:?giPWʤs@uɿ̙3ok9%<4ms9z)DF[]+e_L=2a~55,kl Q ѻr@@ @ïM(  ݼT@?kJ DhD7/C@O4ڄ! -e"y}Wn…¾5zo]M999U1j uaQd@@nn=ʎ P!x6Z0ܯ_`dCa.x0/!CQP[:# (@Z@QV  @% V">F@l թ3  Pϡ@@@mlu Th۷O֮][GP  @ V`l޼Y-ZTGP  @ MN<)gΜQrssMO;wʉ'xQ9rH,@@lVhӧ˞={d۶mruI.]g&M֭[^z'MdE q׮]n:ϲ/\jժy'QQQȖWZUS_u %S<@q;vmVSЛnI ٰa̟?|'fbƌҴiS%~hըQp!m[msm{k[?,))??Zn-;vK,K=dӦMs>5(uz(:vX$K>}03<#SLze2|p孷2A9sdres='SN-Z;l!˗/wyG1-Z$CG}]qׅ3f0Ag @H֭+*HGYlsڵB5kt}dEi&ԩ >gϞ2h O`ٺukM#::ZF)+W4A:@{H55lP֯_/;w4=|jhI{\cbbLoU}GTX埔Tl*TX0ȅ߭St̖d[;kgJJyo;[ۺ\+Pƨs:CS&$$U D 6Ȏ;J\WM6Kی  5?7? oV GڵkK\W+Vȗ_~YfG@ -gΜ]v>JN2=G)%;;r]/[z" 6p/xVրTٻw ҲeK-D/^,f͒&M͛[n2b9q &5k TL1bccŦ:犦)((08mWVM|,ԫYM0بQ#yeԩꫯz?z2eԫWO/ Çˌ3D{'MQ!&N(UV#G ԓ)O@@@\HԹsg|jϥLrJY`9H˳gw}'wy4&&F^|Eg7łOA'iLiii̞@BiSCG233%//ϯM$;>>LU7'}Kq8t6rz/ɑ:t~ڳxw78p@N|||衇cǎ~z^:S L<;v̬}3gNb1  @iVYYYrY>e d߾}rAҞdddرcov[]RRRdȐ!aΝ+2h >|M6'JTTToAg&MdҤI2rH+w}W̙#/6 :TF!-Z0yڵK[O]vԪU:O|'"O H*U$J|\{:8Byp۶vv>V*Zw7'.`ezM73< @.]*&LO>D5kfļ<=zlܸQ.tXAK/oF:w,k֬1_-qqqcY TS3Ǝƌ/ '5jSqLYmzU|V餤$WYG|%+Ж-[7/ #11Q7n,SL1VjҡO?gi&y'Ͷ{Ge2x`3˺uDӥK_y)'Nx^I{XCQfDNby%i* %yyӮnf}j+Y*._7xǧ}ҺukdO %չA5_rjJڶm+_%::Z4N:C+<''Ǫ./ٲelݺPp3cV  ,`me\XsBky뭷v밼k>^ˮ]J߾}ͦw1@Z,)O! .S7oTdUW]U:SE= -p35=ה4ԁ޽{kQ,9sfXVOy$z@^   -'! O!~~T@Vtu   F   $  $@! K4X  h@Ll  ,`I  @@0-[LNꫯʱcNJmw^={v,@@/@dzVLk'+'NȜ9sqwÇ<ӧ'|dРA2ydwuϏw [hC^  "hȫJ^dvmr5._\y>@-Z$CƎy=c ֭5O@@ |?&555J:>ì]4mTn*>b=I)&&~Rܼy<#e6l׮L0SKs OU\@J:/$X ȉ'ٳʶRq_'%㵼JT8}4hР|PJm[M4qRzz:uyǤK D@(?5Tc qsZ7+.]jN2ھ}0LIF|`RMov׷jJDyyz?xD@l4޳gqrq5jT=.yN:ҼysE7Q9qIO>jذDGGѣ@@& lpy뚕% fNgIy\ ./i~^~I7CgΜ)A[&{Z~d -3g YUu^;=CN4QicllOIIOD*mc  VN  @ qP4@@ @#U  a8 @DHlU h7EC@"Q0EbP hvxS֡۹%ڲ$^WkK[e8`KM=k֬)YokTʉ'$33S;Y~YٳgY uVVgɓ'Ӟ׺敝-yyy{ng   X}/+Vŋ%::Zjժ%'Om۶ɔ)SL#ϗW_}UVZ%5jԐÇeȐ!f*UȰaäYfOzJ^z%ϗdٱc7Nڶmyig~䢋./ @Yf+ps *hBv) ,0Ajo2j(IKK3kѣn:c_H׮]۷[o%76Ҁ;2x7RAADEEk3! 8K.:v(7o6hzvfMSN&={AE_f\x&\z!TTn]| 'u]I&u^Qg )fNUV{jϧtf ˄g DuΜ9#j/k׮+]vɥ^jv^+  ? 7C{*dSNݺu+УGsiɒ%ҲeK6o\   -7;" G  : юuPifffj~ǛB\mIz-I뫷ʲrkY8w5:$yyy6TѶv|שSFog}ՁP_2,G@hHX@@/# D9!a LoViѢL0! JI'^~sʇ[7ސW^yE.(;'UV~;Yt\p;G2uTk·A(=A@t[:=??mŦe6ˈ :)ŅM"k;߳>"[v&1C@N &JDB.йsgW^ȏ*W.;r C.иqcC~PkזnA+ =z"mgS'Fz S?@@ 8  @ 0-\~GoF5jd΄/"~zF%555BjG5T`rW]9"[n={W\!iiib],PeƍjtUWz w J+ڎz'7'Eu3?%ͯo{NZn-v 2Dz%qqq)D~Uw- 40J֮ꗋcJzzzku"y{Iϟ?_̙#z-X|dҧO%}5ړ}a5kYֿۛ/yPwC?h?њ7LϦܷo_ΪK,orI;!"z _NsN&߼y&<$"֫:_޽{7lFtԃN]vɨQ{5#z;NNyMw GZjɉ' \>]Ux2R EʽG3{wUp1T4ŕ ?V5 5#4ŝFʅb"Dp1*Ak%A(с7Q \d*DNC:4;{L3\]OKK ;g`XC-tZ[[sHw{vvVƍR^^n:kzɮH|0tk^{N;eeerMY]]5_|)?ϟ?#@e@ zJMXYY)RUUeZŋE/kp'r]ggG;`{6s֏?kLcrrZs$##CN>m5c/@_(< @Z[[Nn߾mfMMeccC޿/ts6ȍL .Hii9 #EEEhΔB "8z IߗiZmLNN-[)))1_TZ6XXXh4뛛6V@ W@$Ao̙3>_˗/挧TT/[֢>.:ׄ1W_1#A70f8j,y/QQQk Z#=FDD@ N} ,>M*))((F3>׌x<288hbcc%..$ WxЅ_R@- @0Y隩~Yy\% fct_count() gss_cat$relig \%>\% fct_anon() \%>\% fct_count() gss_cat$relig \%>\% fct_anon("X") \%>\% fct_count() } forcats/man/pipe.Rd0000644000176200001440000000036613626051403013717 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/utils.R \name{\%>\%} \alias{\%>\%} \title{Pipe operator} \usage{ lhs \%>\% rhs } \description{ See \code{\link[magrittr]{\%>\%}} for more details. } \keyword{internal} forcats/man/fct_drop.Rd0000644000176200001440000000137213626051403014560 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/drop.R \name{fct_drop} \alias{fct_drop} \title{Drop unused levels} \usage{ fct_drop(f, only) } \arguments{ \item{f}{A factor (or character vector).} \item{only}{A character vector restricting the set of levels to be dropped. If supplied, only levels that have no entries and appear in this vector will be removed.} } \description{ Compared to \code{base::droplevels()}, does not drop \code{NA} levels that have values. } \examples{ f <- factor(c("a", "b"), levels = c("a", "b", "c")) f fct_drop(f) # Set only to restrict which levels to drop fct_drop(f, only = "a") fct_drop(f, only = "c") } \seealso{ \code{\link[=fct_expand]{fct_expand()}} to add additional levels to a factor. } forcats/man/fct_cross.Rd0000644000176200001440000000157113626252103014746 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/fct_cross.R \name{fct_cross} \alias{fct_cross} \title{Combine levels from two or more factors to create a new factor} \usage{ fct_cross(..., sep = ":", keep_empty = FALSE) } \arguments{ \item{...}{<\code{\link[rlang:dyn-dots]{dynamic-dots}}> Additional factors or character vectors.} \item{sep}{A character string to separate the levels} \item{keep_empty}{If TRUE, keep combinations with no observations as levels} } \value{ The new factor } \description{ Computes a factor whose levels are all the combinations of the levels of the input factors. } \examples{ fruit <- factor(c("apple", "kiwi", "apple", "apple")) colour <- factor(c("green", "green", "red", "green")) eaten <- c("yes", "no", "yes", "no") fct_cross(fruit, colour) fct_cross(fruit, colour, eaten) fct_cross(fruit, colour, keep_empty = TRUE) } forcats/man/as_factor.Rd0000644000176200001440000000222213626262603014722 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/as_factor.R \name{as_factor} \alias{as_factor} \alias{as_factor.factor} \alias{as_factor.character} \alias{as_factor.numeric} \alias{as_factor.logical} \title{Convert input to a factor} \usage{ as_factor(x, ...) \method{as_factor}{factor}(x, ...) \method{as_factor}{character}(x, ...) \method{as_factor}{numeric}(x, ...) \method{as_factor}{logical}(x, ...) } \arguments{ \item{x}{Object to coerce to a factor.} \item{...}{Other arguments passed down to method.} } \description{ Compared to base R, when \code{x} is a character, this function creates levels in the order in which they appear, which will be the same on every platform. (Base R sorts in the current locale which can vary from place to place.) When \code{x} is numeric, the ordering is based on the numeric value and consistent with base R. } \details{ This is a generic function. } \examples{ # Character object x <- c("a", "z", "g") as_factor(x) as.factor(x) # Character object containing numbers y <- c("1.1", "11", "2.2", "22") as_factor(y) as.factor(y) # Numeric object z <- as.numeric(y) as_factor(z) as.factor(z) } forcats/man/lvls_union.Rd0000644000176200001440000000056713626051403015155 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/lvls.R \name{lvls_union} \alias{lvls_union} \title{Find all levels in a list of factors} \usage{ lvls_union(fs) } \arguments{ \item{fs}{A list of factors.} } \description{ Find all levels in a list of factors } \examples{ fs <- list(factor("a"), factor("b"), factor(c("a", "b"))) lvls_union(fs) } forcats/man/fct_lump.Rd0000644000176200001440000000615613626261320014577 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/lump.R \name{fct_lump} \alias{fct_lump} \alias{fct_lump_min} \alias{fct_lump_prop} \alias{fct_lump_n} \alias{fct_lump_lowfreq} \title{Lump together factor levels into "other"} \usage{ fct_lump( f, n, prop, w = NULL, other_level = "Other", ties.method = c("min", "average", "first", "last", "random", "max") ) fct_lump_min(f, min, w = NULL, other_level = "Other") fct_lump_prop(f, prop, w = NULL, other_level = "Other") fct_lump_n( f, n, w = NULL, other_level = "Other", ties.method = c("min", "average", "first", "last", "random", "max") ) fct_lump_lowfreq(f, other_level = "Other") } \arguments{ \item{f}{A factor (or character vector).} \item{n}{Positive \code{n} preserves the most common \code{n} values. Negative \code{n} preserves the least common \code{-n} values. It there are ties, you will get at least \code{abs(n)} values.} \item{prop}{Positive \code{prop} lumps values which do not appear at least \code{prop} of the time. Negative \code{prop} lumps values that do not appear at most \code{-prop} of the time.} \item{w}{An optional numeric vector giving weights for frequency of each value (not level) in f.} \item{other_level}{Value of level used for "other" values. Always placed at end of levels.} \item{ties.method}{A character string specifying how ties are treated. See \code{\link[=rank]{rank()}} for details.} \item{min}{Preserve levels that appear at least \code{min} number of times.} } \description{ A family for lumping together levels that meet some criteria. \itemize{ \item \code{fct_lump_min()}: lumps levels that appear fewer than \code{min} times. \item \code{fct_lump_prop()}: lumps levels that appear in fewer \code{prop * n} times. \item \code{fct_lump_n()} lumps all levels except for the \code{n} most frequent (or least frequent if \code{n < 0}) \item \code{fct_lump_lowfreq()} lumps together the least frequent levels, ensuring that "other" is still the smallest level. } \code{fct_lump()} exists primarily for historical reasons, as it automatically picks between these different methods depending on its arguments. We no longer recommend that you use it. } \examples{ x <- factor(rep(LETTERS[1:9], times = c(40, 10, 5, 27, 1, 1, 1, 1, 1))) x \%>\% table() x \%>\% fct_lump_n(3) \%>\% table() x \%>\% fct_lump_prop(0.10) \%>\% table() x \%>\% fct_lump_min(5) \%>\% table() x \%>\% fct_lump_lowfreq() \%>\% table() x <- factor(letters[rpois(100, 5)]) x table(x) table(fct_lump_lowfreq(x)) # Use positive values to collapse the rarest fct_lump_n(x, n = 3) fct_lump_prop(x, prop = 0.1) # Use negative values to collapse the most common fct_lump_n(x, n = -3) fct_lump_prop(x, prop = -0.1) # Use weighted frequencies w <- c(rep(2, 50), rep(1, 50)) fct_lump_n(x, n = 5, w = w) # Use ties.method to control how tied factors are collapsed fct_lump_n(x, n = 6) fct_lump_n(x, n = 6, ties.method = "max") # Use fct_lump_min() to lump together all levels with fewer than `n` values table(fct_lump_min(x, min = 10)) table(fct_lump_min(x, min = 15)) } \seealso{ \code{\link[=fct_other]{fct_other()}} to convert specified levels to other. } forcats/man/fct_unique.Rd0000644000176200001440000000057713626051403015130 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/unique.R \name{fct_unique} \alias{fct_unique} \title{Unique values of a factor} \usage{ fct_unique(f) } \arguments{ \item{f}{A factor.} } \description{ Unique values of a factor } \examples{ f <- factor(letters[rpois(100, 10)]) unique(f) # in order of appearance fct_unique(f) # in order of levels } forcats/man/fct_recode.Rd0000644000176200001440000000223413764157244015070 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/recode.R \name{fct_recode} \alias{fct_recode} \title{Change factor levels by hand} \usage{ fct_recode(.f, ...) } \arguments{ \item{.f}{A factor (or character vector).} \item{...}{<\code{\link[rlang:dyn-dots]{dynamic-dots}}> A sequence of named character vectors where the name gives the new level, and the value gives the old level. Levels not otherwise mentioned will be left as is. Levels can be removed by naming them \code{NULL}.} } \description{ Change factor levels by hand } \examples{ x <- factor(c("apple", "bear", "banana", "dear")) fct_recode(x, fruit = "apple", fruit = "banana") # If you make a mistake you'll get a warning fct_recode(x, fruit = "apple", fruit = "bananana") # If you name the level NULL it will be removed fct_recode(x, NULL = "apple", fruit = "banana") # Wrap the left hand side in quotes if it contains special variables fct_recode(x, "an apple" = "apple", "a bear" = "bear") # When passing a named vector to rename levels use !!! to splice x <- factor(c("apple", "bear", "banana", "dear")) levels <- c(fruit = "apple", fruit = "banana") fct_recode(x, !!!levels) } forcats/man/fct_shift.Rd0000644000176200001440000000122413626051403014725 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/shift.R \name{fct_shift} \alias{fct_shift} \title{Shift factor levels to left or right, wrapping around at end} \usage{ fct_shift(f, n = 1L) } \arguments{ \item{f}{A factor.} \item{n}{Positive values shift to the left; negative values shift to the right.} } \description{ This is useful when the levels of an ordered factor are actually cyclical, with different conventions on the starting point. } \examples{ x <- factor( c("Mon", "Tue", "Wed"), levels = c("Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"), ordered = TRUE ) x fct_shift(x) fct_shift(x, 2) fct_shift(x, -1) } forcats/man/fct_reorder.Rd0000644000176200001440000000442413626257051015266 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/reorder.R \name{fct_reorder} \alias{fct_reorder} \alias{fct_reorder2} \alias{last2} \alias{first2} \title{Reorder factor levels by sorting along another variable} \usage{ fct_reorder(.f, .x, .fun = median, ..., .desc = FALSE) fct_reorder2(.f, .x, .y, .fun = last2, ..., .desc = TRUE) last2(.x, .y) first2(.x, .y) } \arguments{ \item{.f}{A factor (or character vector).} \item{.x, .y}{The levels of \code{f} are reordered so that the values of \code{.fun(.x)} (for \code{fct_reorder()}) and \code{fun(.x, .y)} (for \code{fct_reorder2()}) are in ascending order.} \item{.fun}{n summary function. It should take one vector for \code{fct_reorder}, and two vectors for \code{fct_reorder2}, and return a single value.} \item{...}{Other arguments passed on to \code{.fun}. A common argument is \code{na.rm = TRUE}.} \item{.desc}{Order in descending order? Note the default is different between \code{fct_reorder} and \code{fct_reorder2}, in order to match the default ordering of factors in the legend.} } \description{ \code{fct_reorder()} is useful for 1d displays where the factor is mapped to position; \code{fct_reorder2()} for 2d displays where the factor is mapped to a non-position aesthetic. \code{last2()} and \code{first2()} are helpers for \code{fct_reorder2()}; \code{last2()} finds the last value of \code{y} when sorted by \code{x}; \code{first2()} finds the first value. } \examples{ df <- tibble::tribble( ~color, ~a, ~b, "blue", 1, 2, "green", 6, 2, "purple", 3, 3, "red", 2, 3, "yellow", 5, 1 ) df$color <- factor(df$color) fct_reorder(df$color, df$a, min) fct_reorder2(df$color, df$a, df$b) boxplot(Sepal.Width ~ Species, data = iris) boxplot(Sepal.Width ~ fct_reorder(Species, Sepal.Width), data = iris) boxplot(Sepal.Width ~ fct_reorder(Species, Sepal.Width, .desc = TRUE), data = iris) chks <- subset(ChickWeight, as.integer(Chick) < 10) chks <- transform(chks, Chick = fct_shuffle(Chick)) if (require("ggplot2")) { ggplot(chks, aes(Time, weight, colour = Chick)) + geom_point() + geom_line() # Note that lines match order in legend ggplot(chks, aes(Time, weight, colour = fct_reorder2(Chick, Time, weight))) + geom_point() + geom_line() + labs(colour = "Chick") } } forcats/man/fct_expand.Rd0000644000176200001440000000114313626051403015067 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/expand.R \name{fct_expand} \alias{fct_expand} \title{Add additional levels to a factor} \usage{ fct_expand(f, ...) } \arguments{ \item{f}{A factor (or character vector).} \item{...}{Additional levels to add to the factor. Levels that already exist will be silently ignored.} } \description{ Add additional levels to a factor } \examples{ f <- factor(sample(letters[1:3], 20, replace = TRUE)) f fct_expand(f, "d", "e", "f") fct_expand(f, letters[1:6]) } \seealso{ \code{\link[=fct_drop]{fct_drop()}} to drop unused factor levels. } forcats/man/fct_relevel.Rd0000644000176200001440000000277113764156755015301 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/relevel.R \name{fct_relevel} \alias{fct_relevel} \title{Reorder factor levels by hand} \usage{ fct_relevel(.f, ..., after = 0L) } \arguments{ \item{.f}{A factor (or character vector).} \item{...}{Either a function (or formula), or character levels. A function will be called with the current levels, and the return value (which must be a character vector) will be used to relevel the function. Any levels not mentioned will be left in their existing order, after the explicitly mentioned levels. Supports tidy dots.} \item{after}{Where should the new values be placed?} } \description{ This is a generalisation of \code{\link[stats:relevel]{stats::relevel()}} that allows you to move any number of levels to any location. } \examples{ f <- factor(c("a", "b", "c", "d"), levels = c("b", "c", "d", "a")) fct_relevel(f) fct_relevel(f, "a") fct_relevel(f, "b", "a") # Move to the third position fct_relevel(f, "a", after = 2) # Relevel to the end fct_relevel(f, "a", after = Inf) fct_relevel(f, "a", after = 3) # Relevel with a function fct_relevel(f, sort) fct_relevel(f, sample) fct_relevel(f, rev) # Using 'Inf' allows you to relevel to the end when the number # of levels is unknown or variable (e.g. vectorised operations) df <- forcats::gss_cat[, c("rincome", "denom")] lapply(df, levels) df2 <- lapply(df, fct_relevel, "Don't know", after = Inf) lapply(df2, levels) # You'll get a warning if the levels don't exist fct_relevel(f, "e") } forcats/man/fct_shuffle.Rd0000644000176200001440000000055713626051403015254 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/shuffle.R \name{fct_shuffle} \alias{fct_shuffle} \title{Randomly permute factor levels} \usage{ fct_shuffle(f) } \arguments{ \item{f}{A factor (or character vector).} } \description{ Randomly permute factor levels } \examples{ f <- factor(c("a", "b", "c")) fct_shuffle(f) fct_shuffle(f) } forcats/man/fct_count.Rd0000644000176200001440000000130013626051403014733 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/count.R \name{fct_count} \alias{fct_count} \title{Count entries in a factor} \usage{ fct_count(f, sort = FALSE, prop = FALSE) } \arguments{ \item{f}{A factor (or character vector).} \item{sort}{If \code{TRUE}, sort the result so that the most common values float to the top.} \item{prop}{If \code{TRUE}, compute the fraction of marginal table.} } \value{ A tibble with columns \code{f}, \code{n} and \code{p}, if prop is \code{TRUE}. } \description{ Count entries in a factor } \examples{ f <- factor(sample(letters)[rpois(1000, 10)]) table(f) fct_count(f) fct_count(f, sort = TRUE) fct_count(f, sort = TRUE, prop = TRUE) } forcats/DESCRIPTION0000644000176200001440000000230014004341752013414 0ustar liggesusersPackage: forcats Title: Tools for Working with Categorical Variables (Factors) Version: 0.5.1 Authors@R: c(person(given = "Hadley", family = "Wickham", role = c("aut", "cre"), email = "hadley@rstudio.com"), person(given = "RStudio", role = c("cph", "fnd"))) Description: Helpers for reordering factor levels (including moving specified levels to front, ordering by first appearance, reversing, and randomly shuffling), and tools for modifying factor levels (including collapsing rare levels into other, 'anonymising', and manually 'recoding'). License: MIT + file LICENSE URL: https://forcats.tidyverse.org, https://github.com/tidyverse/forcats BugReports: https://github.com/tidyverse/forcats/issues Depends: R (>= 3.2) Imports: ellipsis, magrittr, rlang, tibble Suggests: covr, dplyr, ggplot2, knitr, readr, rmarkdown, testthat VignetteBuilder: knitr Encoding: UTF-8 LazyData: true RoxygenNote: 7.1.1 NeedsCompilation: no Packaged: 2021-01-27 18:16:43 UTC; hadley Author: Hadley Wickham [aut, cre], RStudio [cph, fnd] Maintainer: Hadley Wickham Repository: CRAN Date/Publication: 2021-01-27 19:50:02 UTC forcats/build/0000755000176200001440000000000014004327012013003 5ustar liggesusersforcats/build/vignette.rds0000644000176200001440000000032214004327012015337 0ustar liggesusersb```b`a`f`b2 1#PHs%'妠I{委&d)+@)すQ& 7aD0!)dKME7% 5/$~hZ8S+`zP԰Aհe ,s\ܠL t7`~΢r=xA$Gs=ʕXVr7{fforcats/tests/0000755000176200001440000000000012752645041013063 5ustar liggesusersforcats/tests/testthat/0000755000176200001440000000000014004341752014715 5ustar liggesusersforcats/tests/testthat/test-match.R0000644000176200001440000000052613626051403017114 0ustar liggesuserscontext("test-fct_match.R") test_that("equivalent to %in% when levels present", { f <- factor(c("a", "b", "c", NA)) expect_equal(fct_match(f, "a"), f %in% "a") expect_equal(fct_match(f, NA), f %in% NA) }) test_that("error when levels are missing", { f <- factor(c("a", "b", "c")) expect_error(fct_match(f, "d"), "not present") }) forcats/tests/testthat/test-relevel.R0000644000176200001440000000200313626051403017446 0ustar liggesuserscontext("fct_relevel") test_that("warns about unknown levels", { f1 <- factor(c("a", "b")) expect_warning(f2 <- fct_relevel(f1, "d"), "Unknown levels") expect_equal(levels(f2), levels(f1)) }) test_that("moves supplied levels to front", { f1 <- factor(c("a", "b", "c", "d")) f2 <- fct_relevel(f1, "c", "b") expect_equal(levels(f2), c("c", "b", "a", "d")) }) test_that("can moves supplied levels to end", { f1 <- factor(c("a", "b", "c", "d")) f2 <- fct_relevel(f1, "a", "b", after = 2) f3 <- fct_relevel(f1, "a", "b", after = Inf) expect_equal(levels(f2), c("c", "d", "a", "b")) expect_equal(levels(f3), c("c", "d", "a", "b")) }) test_that("can relevel with function ", { f1 <- fct_rev(factor(c("a", "b"))) f2a <- fct_relevel(f1, rev) f2b <- fct_relevel(f1, ~ rev(.)) expect_equal(levels(f2a), c("a", "b")) expect_equal(levels(f2b), c("a", "b")) }) test_that("function must return character vector", { f <- factor(c("a", "b")) expect_error(fct_relevel(f, ~ 1), "character vector") }) forcats/tests/testthat/test-lump.R0000644000176200001440000001412413626261320016775 0ustar liggesuserscontext("fct_lump") test_that("too many arguments fails", { f <- c("a", "b", "c") expect_error(fct_lump(f, n = 1, count = 1)) expect_error(fct_lump(f, n = 1, prop = 0.1)) expect_error(fct_lump(f, min = 2, count = 1)) }) test_that("positive values keeps most commmon", { f <- c("a", "a", "a", "b", "b", "c", "d", "e", "f", "g") expect_equal(levels(fct_lump(f, n = 1)), c("a", "Other")) expect_equal(levels(fct_lump(f, n = 2)), c("a", "b", "Other")) expect_equal(levels(fct_lump(f, prop = 0.25)), c("a", "Other")) expect_equal(levels(fct_lump(f, prop = 0.15)), c("a", "b", "Other")) }) test_that("ties are respected", { f <- c("a", "a", "a", "b", "b", "b", "c", "d") expect_equal(levels(fct_lump(f, 1)), c("a", "b", "Other")) }) test_that("negative values drop most common" ,{ f <- c("a", "a", "a", "a", "b", "b", "b", "b", "c", "d") expect_equal(levels(fct_lump(f, n = -1)), c("c", "d", "Other")) expect_equal(levels(fct_lump(f, prop = -0.2)), c("c", "d", "Other")) }) test_that("return original factor when all element satisfy n / p condition", { f <- c("a", "a", "a", "b", "b", "c", "d", "e", "f", "g") expect_equal(levels(fct_lump(f, n = 4)), c("a", "b", "c", "d", "e", "f", "g")) expect_equal(levels(fct_lump(f, n = 10)), c("a", "b", "c", "d", "e", "f", "g")) expect_equal(levels(fct_lump(f, n = -10)), c("a", "b", "c", "d", "e", "f", "g")) expect_equal(levels(fct_lump(f, prop = 0.01)), c("a", "b", "c", "d", "e", "f", "g")) expect_equal(levels(fct_lump(f, prop = -1)), c("a", "b", "c", "d", "e", "f", "g")) }) test_that("different behaviour when apply tie function", { f <- c("a", "a", "a", "b", "b", "c", "d", "e", "f", "g") expect_equal(levels(fct_lump(f, n = 4, ties.method = "min")), c("a", "b", "c", "d", "e", "f", "g")) expect_equal(levels(fct_lump(f, n = 4, ties.method = "max")), c("a", "b", "Other" )) # Rank of c, d, e, f, g is (3+4+5+6+7)/5 = 5 expect_equal(levels(fct_lump(f, n = 4, ties.method = "average")), c("a", "b", "Other" )) expect_equal(levels(fct_lump(f, n = 5, ties.method = "average")), c("a", "b", "c", "d", "e", "f", "g")) expect_equal(levels(fct_lump(f, n = 4, ties.method = "first")), c("a", "b", "c", "d", "Other")) if (getRversion() >= "3.3.0") { expect_equal(levels(fct_lump(f, n = 4, ties.method = "last")), c("a", "b", "f", "g", "Other")) } }) test_that("NAs included in total", { f <- factor(c("a", "a", "b", "c", rep(NA, 7))) o1 <- fct_lump(f, prop = 0.10) expect_equal(levels(o1), c("a", "Other")) o2 <- fct_lump(f, w = rep(1, 11), prop = 0.10) expect_equal(levels(o2), c("a", "Other")) }) test_that("bad weights generate error messages", { expect_error(fct_lump(letters, w = letters), "must be a numeric vector") expect_error(fct_lump(letters, w = 1:10), "must be the same length") expect_error(fct_lump(letters, w = rep(-1, 26)), "must be non-negative") }) test_that("values are correctly weighted", { f <- c("a", "a", "a", "b", "b", "c", "d", "e", "f", "g") w <- c( 0.2, 0.2, 0.6, 2, 2, 6, 4, 2, 2, 1) f2 <- c( "a", rep("b", 4), rep("c", 6), rep("d", 4), rep("e", 2), rep("f", 2), "g" ) expect_equal(levels(fct_lump(f, w = w)), levels(fct_lump(f2))) expect_equal( levels(fct_lump(f, n = 1, w = w)), levels(fct_lump(f2, n = 1)) ) expect_equal( levels(fct_lump(f, n = -2, w = w, ties.method = "first")), levels(fct_lump(f2, n = -2, ties.method = "first")) ) expect_equal( levels(fct_lump(f, n = 99, w = w)), levels(fct_lump(f2, n = 99)) ) expect_equal( levels(fct_lump(f, prop = 0.01, w = w)), levels(fct_lump(f2, prop = 0.01)) ) expect_equal( levels(fct_lump(f, prop = -0.25, w = w, ties.method = "max")), levels(fct_lump(f2, prop = -0.25, ties.method = "max")) ) }) test_that("do not change the label when no lumping occurs", { f <- c("a", "a", "a", "a", "b", "b", "b", "c", "c", "d") expect_equal(levels(fct_lump(f, n = 3)), c("a", "b", "c", "d")) expect_equal(levels(fct_lump(f, prop = 0.1)), c("a", "b", "c", "d")) }) test_that("only have one small other level", { f <- c("a", "a", "a", "a", "b", "b", "b", "c", "c", "d") expect_equal(levels(fct_lump(f)), c("a", "b", "c", "Other")) }) test_that("fct_lump_min works when not weighted", { f <- c("a", "a", "a", "b", "b", "c", "d", "e", "f", "g") expect_equal(levels(fct_lump_min(f, min = 3)), c("a", "Other")) expect_equal(levels(fct_lump_min(f, min = 2)), c("a", "b", "Other")) }) test_that("fct_lump_min works when weighted", { f <- c("a", "b", "c", "d", "e") w <- c( 0.2, 2, 6, 4, 1) expect_equal(levels(fct_lump_min(f, min = 6, w = w)), c("c", "Other")) expect_equal(levels(fct_lump_min(f, min = 1.5, w = w)), c("b", "c", "d", "Other")) }) test_that("throws error if n or prop is not numeric", { f <- c("a", "a", "a", "a", "b", "b", "b", "c", "c", "d") expect_error(fct_lump(f, n = "2"), "`n`") expect_error(fct_lump(f, prop = "2"), "`prop`") }) test_that("fct_lump_prop works when not weighted", { f <- c("a", "a", "a", "b", "b", "c", "d", "e", "f", "g") expect_equal(levels(fct_lump_prop(f, prop = 0.2)), c("a", "Other")) expect_equal(levels(fct_lump_prop(f, prop = 0.1)), c("a", "b", "Other")) }) test_that("fct_lump_prop works when weighted", { f <- c("a", "b", "c", "d", "e") w <- c( 0.2, 2, 6, 4, 1) expect_equal(levels(fct_lump_prop(f, prop = 0.3, w = w)), c("c", "d", "Other")) expect_equal(levels(fct_lump_prop(f, prop = 0.2, w = w)), c("c", "d", "Other")) }) # Default ----------------------------------------------------------------- test_that("lumps smallest", { expect_equal(lump_test(c(1, 2, 3, 6)), "Xbcd") expect_equal(lump_test(c(1, 2, 3, 7)), "XXXd") expect_equal(lump_test(c(1, 2, 3, 7, 13)), "XXXde") expect_equal(lump_test(c(1, 2, 3, 7, 14)), "XXXXe") }) test_that("doesn't lump if none small enough", { expect_equal(lump_test(c(2, 2, 4)), "abc") }) test_that("order doesn't matter", { expect_equal(lump_test(c(2, 2, 5)), "XXc") expect_equal(lump_test(c(2, 5, 2)), "XbX") expect_equal(lump_test(c(5, 2, 2)), "aXX") }) forcats/tests/testthat/test-fct_relabel.R0000644000176200001440000000223213626051403020256 0ustar liggesuserscontext("fct_relabel") test_that("identity", { f1 <- factor(c("a", "b")) expect_identical(fct_relabel(f1, identity), f1) }) test_that("error if not function", { f1 <- factor("a") expect_error(fct_relabel(f1, 1), "function") }) test_that("error if level not character", { f1 <- factor("a") expect_error(fct_relabel(f1, function(x) 1), "character") }) test_that("error if level has different length", { f1 <- factor(letters) expect_error(fct_relabel(f1, function(x) x[-1]), "expected 26.*got 25") }) test_that("total collapse", { f1 <- factor(letters) new_levels <- function(x) rep("1", length(x)) expect_identical(fct_relabel(f1, new_levels), factor(new_levels(letters))) }) test_that("additional arguments", { f1 <- factor(letters) expect_identical(fct_relabel(f1, paste0, "."), factor(paste0(letters, "."))) }) test_that("formulas are coerced to functions", { f1 <- factor(letters) expect_identical( fct_relabel(f1, ~paste0(.x, ".")), factor(paste0(letters, ".")) ) }) test_that("string input is coerced to a factor", { expect_identical( fct_relabel(LETTERS[1:2], .fun=function(x) x), factor(LETTERS[1:2]) ) })forcats/tests/testthat/test-anon.R0000644000176200001440000000047213626051403016753 0ustar liggesuserscontext("test-anon.R") test_that("new levels are padded numerics", { f1 <- factor(letters[1:10]) f2 <- fct_anon(f1) expect_equal(levels(f2), sprintf("%02d", 1:10)) }) test_that("prefix added to start of level", { f1 <- factor("x") f2 <- fct_anon(f1, prefix = "X") expect_equal(levels(f2), "X1") }) forcats/tests/testthat/test-collapse.R0000644000176200001440000000340313626261320017620 0ustar liggesuserscontext("test-collapse.R") test_that("can collapse multiple values", { f1 <- factor(letters[1:3]) f2 <- fct_collapse(f1, x = c("a", "b"), y = "c") expect_equal(f2, factor(c("x", "x", "y"))) }) test_that("empty dots yields unchanged factor", { f1 <- factor(letters[1:3]) f2 <- fct_collapse(f1) expect_identical(f1, f2) }) test_that("can collapse missing levels", { f1 <- factor(c("x", NA), exclude = NULL) f2 <- fct_collapse(f1, y = NA_character_) expect_equal(f2, factor(c("x", "y"))) }) test_that("can collapse un-named levels to Other", { f1 <- factor(letters[1:3]) f2 <- fct_collapse(f1, xy = c("a", "b"), other_level = "Other") expect_equal(f2, factor(c("xy", "xy", "Other"), levels = c("xy", "Other"))) }) test_that("collapses levels correctly when group_other is TRUE but no other variables to group", { f1 <- factor(letters[1:4]) f2 <- fct_collapse(f1, x1 = c("a", "b", "d"), x2 = "c", other_level = "Other") expect_equal(f2, factor(c("x1", "x1", "x2", "x1"), levels = c("x1", "x2"))) }) test_that("collapses levels correctly when group_other is TRUE and some Other variables to group", { f1 <- factor(letters[1:4]) f2 <- fct_collapse(f1, x1 = c("a", "d"), x2 = "c", other_level = "Other") expect_equal(f2, factor(c("x1", "Other", "x2", "x1"), levels = c("x1", "x2", "Other"))) }) test_that("does not automatically collapse unnamed levels to Other", { f1 <- factor(letters[1:3]) f2 <- fct_collapse(f1, xy = c("a", "b")) expect_equal(f2, factor(c("xy", "xy", "c"), levels = c("xy", "c"))) }) test_that("group_other is deprecated", { f1 <- factor(letters[1:4]) f2 <- expect_warning( fct_collapse(f1, x1 = c("a", "d"), x2 = "c", group_other = TRUE), "deprecated" ) expect_equal(levels(f2), c("x1", "x2", "Other")) }) forcats/tests/testthat/test-count.R0000644000176200001440000000146213626257051017157 0ustar liggesuserscontext("test-count.R") test_that("0 count for empty levels", { f <- factor(levels = c("a", "b")) expect_equal(fct_count(f)$n, c(0, 0)) f <- factor("a", levels = c("a", "b", "c")) expect_equal(fct_count(f)$n, c(1, 0, 0)) }) test_that("counts NA even when not in levels", { f <- factor(c("a", "a", NA)) out <- fct_count(f) expect_equal(out$n, c(2, 1)) # and doesn't change levels expect_equal(levels(out$f), levels(f)) }) test_that("returns marginal table", { f <- factor(c("a", "a", "b")) out <- fct_count(f, prop = TRUE) expect_equal(out$n, c(2, 1)) expect_equal(out$p, c(2, 1) / 3) }) test_that("sort = TRUE brings most frequent values to top", { f <- factor(c("a", "b", "b")) out <- fct_count(f, sort = TRUE) expect_equal(out$f, factor(c("b", "a"), levels = c("a", "b"))) }) forcats/tests/testthat/test-reorder.R0000644000176200001440000000336713626257051017477 0ustar liggesuserscontext("test-reorder.R") test_that("can reorder by 2d summary", { df <- tibble::tribble( ~g, ~x, "a", 3, "a", 3, "b", 2, "b", 2, "b", 1 ) f1 <- fct_reorder(df$g, df$x) expect_equal(levels(f1), c("b", "a")) f2 <- fct_reorder(df$g, df$x, .desc = TRUE) expect_equal(levels(f2), c("a", "b")) }) test_that("can reorder by 2d summary", { df <- tibble::tribble( ~g, ~x, ~y, "a", 1, 10, "a", 2, 5, "b", 1, 5, "b", 2, 10 ) f1 <- fct_reorder2(df$g, df$x, df$y) expect_equal(levels(f1), c("b", "a")) f2 <- fct_reorder(df$g, df$x, .desc = TRUE) expect_equal(levels(f2), c("a", "b")) }) test_that("complains if summary doesn't return single value", { fun1 <- function(x, y) c(1, 2) fun2 <- function(x, y) integer() expect_error(fct_reorder("a", 1, fun1), "single value per group") expect_error(fct_reorder("a", 1, fun2), "single value per group") expect_error(fct_reorder2("a", 1, 2, fun1), "single value per group") expect_error(fct_reorder2("a", 1, 2, fun2), "single value per group") }) test_that("fct_infreq respects missing values", { f <- factor(c("a", "b", "b", NA, NA, NA), exclude = FALSE) expect_equal(levels(fct_infreq(f)), c(NA, "b", "a")) }) test_that("fct_inseq sorts in numeric order", { x <- c("1", "2", "3") expect_equal( fct_inseq(factor(x, levels = c("3", "1", "2"))), factor(x, levels = c("1", "2", "3")) ) # non-numeric go to end x <- c("1", "2", "3", "a") expect_equal( fct_inseq(factor(x, levels = c("a", "3", "1", "2"))), factor(x, levels = c("1", "2", "3", "a")) ) }) test_that("fct_inseq gives error for non-numeric levels", { f <- factor(c("c", "a", "a", "b")) expect_error(levels(fct_inseq(f)), "level must be coercible to numeric") }) forcats/tests/testthat/test-fct_other.R0000644000176200001440000000104213626051403017767 0ustar liggesuserscontext("fct_other") test_that("keeps levels in keep", { x1 <- factor(c("a", "b")) x2 <- fct_other(x1, keep = "a") expect_equal(levels(x2), c("a", "Other")) }) test_that("drops levels in drop", { x1 <- factor(c("a", "b")) x2 <- fct_other(x1, drop = "a") # other always placed at end expect_equal(levels(x2), c("b", "Other")) }) test_that("must supply exactly one of drop and keep", { f <- factor(c("a", "b")) expect_error(fct_other(f), "exactly one") expect_error(fct_other(f, keep = "a", drop = "a"), "exactly one") }) forcats/tests/testthat/test-fct_recode.R0000644000176200001440000000213513626051403020113 0ustar liggesuserscontext("fct_recode") test_that("warns about unknown levels", { f1 <- factor(c("a", "b")) expect_warning(f2 <- fct_recode(f1, d = "e"), "Unknown levels") expect_equal(levels(f2), levels(f1)) }) test_that("can collapse levels", { f1 <- factor(c("a1", "a2", "b1", "b2")) f2 <- factor(c("a", "a", "b", "b")) expect_equal(fct_recode(f1, a = "a1", a = "a2", b = "b1", b = "b2"), f2) }) test_that("can recode multiple levels to NA", { f1 <- factor(c("a1", "empty", "a2", "b", "missing")) f2 <- factor(c("a", NA, "a", "b", NA)) expect_equal(fct_recode(f1, NULL = "missing", NULL = "empty", a = "a1", a = "a2"), f2) }) test_that("can just remove levels", { f1 <- factor(c("a", "missing")) f2 <- factor(c("a", NA)) expect_equal(fct_recode(f1, NULL = "missing"), f2) }) # check_recode_levels ----------------------------------------------------- test_that("new levels must be character", { expect_error(check_recode_levels(a = 1), "Problems at positions: 1") }) test_that("new levels must be length 1", { expect_error(check_recode_levels(a = c("a", "b")), "Problems at positions: 1") }) forcats/tests/testthat/test-shift.R0000644000176200001440000000060313626051403017131 0ustar liggesuserscontext("test-shift.R") test_that("can shift in either direction", { f1 <- factor(c("a", "b", "c")) f2_l <- fct_shift(f1, 1) expect_equal(levels(f2_l), c("b", "c", "a")) f2_r <- fct_shift(f1, -1) expect_equal(levels(f2_r), c("c", "a", "b")) }) test_that("0 shift leaves unchanged", { f1 <- factor(c("a", "b", "c")) f2 <- fct_shift(f1, 0) expect_identical(f1, f2) }) forcats/tests/testthat/test-fct_c.R0000644000176200001440000000057013626051403017075 0ustar liggesuserscontext("fct_c") test_that("uses tidy_dots", { fs <- list(factor("a"), factor("b")) fab <- factor(c("a", "b")) expect_equal(fct_c(!!!fs), fab) expect_equal(fct_c(fs[[1]], fs[[2]]), fab) }) test_that("all inputs must be factors", { expect_error(fct_c("a"), "must be factors") }) test_that("empty input yields empty factor", { expect_equal(fct_c(), factor()) }) forcats/tests/testthat/test-fct_cross.R0000644000176200001440000000412713626252103020006 0ustar liggesuserscontext("fct_cross") test_that("empty input returns empty factor", { expect_equal(fct_cross(), factor()) }) test_that("gives correct levels", { fruit <- as_factor(c("apple", "kiwi", "apple", "apple")) colour <- as_factor(c("green", "green", "red", "green")) f2 <- fct_cross(fruit, colour) expect_setequal(levels(f2), c("apple:green", "kiwi:green", "apple:red")) }) test_that("recycle inputs", { expect_length(fct_cross("a", c("a", "b", "c"), "d"), 3) expect_error(fct_cross(c("a", "b", "c"), c("a", "b")), "recycle", class = "error") }) test_that("keeps empty levels when requested", { fruit <- as_factor(c("apple", "kiwi", "apple", "apple")) colour <- as_factor(c("green", "green", "red", "green")) f2 <- fct_cross(fruit, colour, keep_empty = TRUE) expect_setequal(levels(f2), c("apple:green", "kiwi:green", "apple:red", "kiwi:red")) }) test_that("order of levels is preserved", { fruit <- as_factor(c("apple", "kiwi", "apple", "apple")) colour <- as_factor(c("green", "green", "red", "green")) fruit <- fct_relevel(fruit, c("kiwi", "apple")) colour <- fct_relevel(colour, c("red", "green")) f2 <- fct_cross(fruit, colour) expect_setequal(levels(f2), c("kiwi:green", "apple:red", "apple:green")) }) test_that("gives NA output on NA input", { fruit <- as_factor(c("apple", "kiwi", "apple", "apple")) colour <- as_factor(c("green", "green", "red", "green")) fruit[1] <- NA f2 <- fct_cross(fruit, colour) expect_true(is.na(f2[1])) }) test_that("gives NA output on NA input, when keeping empty levels", { fruit <- as_factor(c("apple", "kiwi", "apple", "apple")) colour <- as_factor(c("green", "green", "red", "green")) fruit[1] <- NA f2 <- fct_cross(fruit, colour, keep_empty = TRUE) expect_true(is.na(f2[1])) }) test_that("can combine more than two factors", { fruit <- as_factor(c("apple", "kiwi", "apple", "apple")) colour <- as_factor(c("green", "green", "red", "green")) eaten <- c("yes", "no", "yes", "no") f2 <- fct_cross(fruit, colour, eaten) expect_setequal(levels(f2), c("apple:green:no", "apple:green:yes", "apple:red:yes", "kiwi:green:no")) }) forcats/tests/testthat/test-explicit_na.R0000644000176200001440000000074613626051403020323 0ustar liggesuserscontext("test-explicit_na.R") test_that("factor unchanged if no missing levels", { f1 <- factor(letters[1:3]) f2 <- fct_explicit_na(f1) expect_identical(f1, f2) }) test_that("converts implicit NA", { f1 <- factor(c("a", NA)) f2 <- fct_explicit_na(f1) expect_equal(f2, fct_inorder(c("a", "(Missing)"))) }) test_that("converts explicit NA", { f1 <- factor(c("a", NA), exclude = NULL) f2 <- fct_explicit_na(f1) expect_equal(f2, fct_inorder(c("a", "(Missing)"))) }) forcats/tests/testthat/test-lvls_reorder.R0000644000176200001440000000214613626051403020522 0ustar liggesuserscontext("lvls_reorder") test_that("changes levels, not values", { f1 <- factor(c("a", "b")) f2 <- factor(c("a", "b"), levels = c("b", "a")) expect_equal(lvls_reorder(f1, 2:1), f2) }) test_that("idx must be numeric", { f <- factor(c("a", "b")) expect_error(lvls_reorder(f, "a"), "must be numeric") }) test_that("must have one integer per level", { f <- factor(c("a", "b", "c")) expect_error(lvls_reorder(f, c(1, 2)), "one integer for each level") expect_error(lvls_reorder(f, c(1, 2, 2)), "one integer for each level") expect_error(lvls_reorder(f, c(1, 2.5)), "one integer for each level") }) test_that("can change ordered status of output", { f1 <- factor(letters[1:3]) f2 <- ordered(f1) expect_equal(is.ordered(lvls_reorder(f1, 1:3)), FALSE) expect_equal(is.ordered(lvls_reorder(f1, 1:3, ordered = FALSE)), FALSE) expect_equal(is.ordered(lvls_reorder(f1, 1:3, ordered = TRUE)), TRUE) expect_equal(is.ordered(lvls_reorder(f2, 1:3)), TRUE) expect_equal(is.ordered(lvls_reorder(f2, 1:3, ordered = FALSE)), FALSE) expect_equal(is.ordered(lvls_reorder(f2, 1:3, ordered = TRUE)), TRUE) }) forcats/tests/testthat/test-fct_drop.R0000644000176200001440000000116213626051403017615 0ustar liggesuserscontext("fct_drop") test_that("doesn't add NA level", { f1 <- factor(c("a", NA), levels = c("a", "b")) f2 <- fct_drop(f1) expect_equal(levels(f2), "a") }) test_that("can optionally restrict levels to drop", { f1 <- factor("a", levels = c("a", "b", "c")) expect_equal(levels(fct_drop(f1, only = "b")), c("a", "c")) expect_equal(levels(fct_drop(f1, only = "a")), c("a", "b", "c")) }) test_that("preserves ordered class and attributes", { f1 <- ordered(letters[1:2], letters[1:3]) attr(f1, "x") <- "test" f2 <- fct_drop(f1) expect_s3_class(f2, "ordered") expect_equal(attr(f2, "x"), attr(f1, "x")) }) forcats/tests/testthat/test-utils.R0000644000176200001440000000042213626051403017153 0ustar liggesuserscontext("test-utils.R") test_that("check_factor() fails when needed", { expect_error(check_factor(NA), "factor") }) test_that("check_factor_list() fails when needed", { expect_error(check_factor_list(1), "list") expect_error(check_factor_list(list(1)), "factor") }) forcats/tests/testthat/test-shuffle.R0000644000176200001440000000026513626051403017454 0ustar liggesuserscontext("test-shuffle.R") test_that("reproducibility shuffles", { set.seed(1014) f1 <- factor(c("a", "b")) f2 <- fct_shuffle(f1) expect_equal(levels(f2), c("a", "b")) }) forcats/tests/testthat/test-rev.R0000644000176200001440000000022713626051403016612 0ustar liggesuserscontext("test-rev.R") test_that("reverses levels", { f1 <- factor(c("a", "b", "a")) f2 <- fct_rev(f1) expect_equal(levels(f2), c("b", "a")) }) forcats/tests/testthat/test-as_factor.R0000644000176200001440000000073113626461724017772 0ustar liggesuserscontext("as_factor") test_that("equivalent to fct_inorder", { x <- c("a", "z", "g") expect_equal(as_factor(x), fct_inorder(x)) }) test_that("leaves factors as is", { f1 <- factor(letters) f2 <- as_factor(f1) expect_identical(f1, f2) }) test_that("logical has fixed levels", { f <- as_factor(FALSE) expect_equal(levels(f), c("FALSE", "TRUE")) }) test_that("supports NA (#89)", { x <- c("a", "z", "g", NA) expect_equal(as_factor(x), fct_inorder(x)) }) forcats/tests/testthat/helper-lump.R0000644000176200001440000000015012754332005017267 0ustar liggesuserslump_test <- function(x) { paste(ifelse(in_smallest(x), "X", letters[seq_along(x)]), collapse = "") } forcats/tests/testthat/test-lvls.R0000644000176200001440000000246613626051403017005 0ustar liggesuserscontext("lvls") # lvls_expand ------------------------------------------------------------- test_that("changes levels, not values", { f1 <- factor(c("a")) f2 <- factor(c("a"), levels = c("a", "b")) expect_equal(lvls_expand(f1, c("a", "b")), f2) }) test_that("must include all existing levels", { f1 <- factor(c("a", "b")) expect_error(lvls_expand(f1, c("a", "c")), "include all existing levels") }) # lvls_revalue ------------------------------------------------------------ test_that("changes values and levels", { f1 <- factor(c("a", "b")) f2 <- factor(c("b", "a"), levels = c("b", "a")) expect_equal(lvls_revalue(f1, c("b", "a")), f2) }) test_that("can collapse values", { f1 <- factor(c("a", "b")) f2 <- factor(c("a", "a")) expect_equal(lvls_revalue(f1, c("a", "a")), f2) }) test_that("preserves missing values", { f1 <- factor(c("a", NA), exclude = NULL) f2 <- lvls_revalue(f1, levels(f1)) expect_equal(levels(f2), levels(f1)) }) test_that("`new_levels` must be a character", { f1 <- factor(c("a", "b")) expect_error(lvls_revalue(f1, 1:5), "character vector") }) test_that("`new_levels` must be same length as existing levels", { f1 <- factor(c("a", "b")) expect_error(lvls_revalue(f1, c("a")), "same length") expect_error(lvls_revalue(f1, c("a", "b", "c")), "same length") }) forcats/tests/testthat.R0000644000176200001440000000007212752645041015045 0ustar liggesuserslibrary(testthat) library(forcats) test_check("forcats") forcats/vignettes/0000755000176200001440000000000014004327013013715 5ustar liggesusersforcats/vignettes/forcats.Rmd0000644000176200001440000001214514004267612016035 0ustar liggesusers--- title: "Introduction to forcats" author: "Emily Robinson" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Introduction to forcats} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r setup, include = FALSE} knitr::opts_chunk$set( collapse = TRUE, comment = "#>" ) ``` The goal of the __forcats__ package is to provide a suite of useful tools that solve common problems with factors. Factors are useful when you have categorical data, variables that have a fixed and known set of values, and when you want to display character vectors in non-alphabetical order. If you want to learn more, the best place to start is the [chapter on factors](https://r4ds.had.co.nz/factors.html) in R for Data Science. ## Ordering by frequency ```{r message = FALSE} library(dplyr) library(ggplot2) library(forcats) ``` Let's try answering the question, "what are the most common hair colors of star wars characters?" Let's start off by making a bar plot: ```{r initial-plot} ggplot(starwars, aes(x = hair_color)) + geom_bar() + coord_flip() ``` That's okay, but it would be more helpful the graph was ordered by count. This is a case of an **unordered** categorical variable where we want it ordered by its frequency. To do so, we can use the function `fct_infreq()`: ```{r fct-infreq-hair} ggplot(starwars, aes(x = fct_infreq(hair_color))) + geom_bar() + coord_flip() ``` Note that `fct_infreq()` it automatically puts NA at the top, even though that doesn't have the smallest number of entries. ## Combining levels Let's take a look at skin color now: ```{r} starwars %>% count(skin_color, sort = TRUE) ``` We see that there's 31 different skin colors - if we want to make a plot this would be way too many to display! Let's reduce it to only be the top 5. We can use `fct_lump()` to "lump" all the infrequent colors into one factor, "other." The argument `n` is the number of levels we want to keep. ```{r} starwars %>% mutate(skin_color = fct_lump(skin_color, n = 5)) %>% count(skin_color, sort = TRUE) ``` We could also have used `prop` instead, which keeps all the levels that appear at least `prop` of the time. For example, let's keep skin colors that at least 10% of the characters have: ```{r} starwars %>% mutate(skin_color = fct_lump(skin_color, prop = .1)) %>% count(skin_color, sort = TRUE) ``` Only light and fair remain; everything else is other. If you wanted to call it something than "other", you can change it with the argument `other_level`: ```{r} starwars %>% mutate(skin_color = fct_lump(skin_color, prop = .1, other_level = "extra")) %>% count(skin_color, sort = TRUE) ``` What if we wanted to see if the average mass differed by eye color? We'll only look at the 6 most popular eye colors and remove `NA`s. ```{r fct-lump-mean} avg_mass_eye_color <- starwars %>% mutate(eye_color = fct_lump(eye_color, n = 6)) %>% group_by(eye_color) %>% summarise(mean_mass = mean(mass, na.rm = TRUE)) avg_mass_eye_color ``` ## Ordering by another variable It looks like people (or at least one person) with orange eyes are definitely heavier! If we wanted to make a graph, it would be nice if it was ordered by `mean_mass`. We can do this with `fct_reorder()`, which reorders one variable by another. ```{r fct-reorder} avg_mass_eye_color %>% mutate(eye_color = fct_reorder(eye_color, mean_mass)) %>% ggplot(aes(x = eye_color, y = mean_mass)) + geom_col() ``` ## Manually reordering Let's switch to using another dataset, `gss_cat`, the general social survey. What is the income distribution among the respondents? ```{r} gss_cat %>% count(rincome) ``` Notice that the income levels are in the correct order - they start with the non-answers and then go from highest to lowest. This is the same order you'd see if you plotted it as a bar chart. This is not a coincidence. When you're working with ordinal data, where there is an order, you can have an ordered factor. You can examine them with the base function `levels()`, which prints them in order: ```{r} levels(gss_cat$rincome) ``` But what if your factor came in the wrong order? Let's simulate that by reordering the levels of `rincome` randomly with `fct_shuffle()`: ```{r} reshuffled_income <- gss_cat$rincome %>% fct_shuffle() levels(reshuffled_income) ``` Now if we plotted it, it would show in this order, which is all over the place! How can we fix this and put it in the right order? We can use the function `fct_relevel()` when we need to manually reorder our factor levels. In addition to the factor, you give it a character vector of level names, and specify where you want to move them. It defaults to moving them to the front, but you can move them after another level with the argument `after`. If you want to move it to the end, you set `after` equal to `Inf`. For example, let's say we wanted to move `Lt $1000` and `$1000 to 2999` to the front. We would write: ```{r} fct_relevel(reshuffled_income, c("Lt $1000", "$1000 to 2999")) %>% levels() ``` What if we want to move them to the second and third place? ```{r} fct_relevel(reshuffled_income, c("Lt $1000", "$1000 to 2999"), after = 1) %>% levels() ``` forcats/R/0000755000176200001440000000000013764156755012137 5ustar liggesusersforcats/R/count.R0000644000176200001440000000151413626257051013377 0ustar liggesusers#' Count entries in a factor #' #' @param f A factor (or character vector). #' @param sort If `TRUE`, sort the result so that the most common values #' float to the top. #' @param prop If `TRUE`, compute the fraction of marginal table. #' @return A tibble with columns `f`, `n` and `p`, if prop is `TRUE`. #' @export #' @examples #' f <- factor(sample(letters)[rpois(1000, 10)]) #' table(f) #' fct_count(f) #' fct_count(f, sort = TRUE) #' fct_count(f, sort = TRUE, prop = TRUE) fct_count <- function(f, sort = FALSE, prop = FALSE) { f2 <- check_factor(f) n_na <- sum(is.na(f)) df <- tibble::tibble( f = fct_inorder(c(levels(f2), if (n_na > 0) NA)), n = c(tabulate(f2, nlevels(f)), if (n_na > 0) n_na) ) if (sort) { df <- df[order(df$n, decreasing = TRUE), ] } if (prop) { df$p <- prop.table(df$n) } df } forcats/R/rev.R0000644000176200001440000000044613626051403013037 0ustar liggesusers#' Reverse order of factor levels #' #' This is sometimes useful when plotting a factor. #' #' @param f A factor (or character vector). #' @export #' @examples #' f <- factor(c("a", "b", "c")) #' fct_rev(f) fct_rev <- function(f) { f <- check_factor(f) lvls_reorder(f, rev(lvls_seq(f))) } forcats/R/utils.R0000644000176200001440000000125113626051403013376 0ustar liggesusers#' Pipe operator #' #' See \code{\link[magrittr]{\%>\%}} for more details. #' #' @name %>% #' @rdname pipe #' @keywords internal #' @export #' @importFrom magrittr %>% #' @usage lhs \%>\% rhs NULL check_factor <- function(f) { if (is.character(f)) { factor(f) } else if (is.factor(f)) { f } else { stop("`f` must be a factor (or character vector).", call. = FALSE) } } check_factor_list <- function(fs, arg_name = "fs") { if (!is.list(fs)) { stop("`fs` must be a list", call. = FALSE) } is_factor <- vapply(fs, is.factor, logical(1)) if (any(!is_factor)) { stop("All elements of `", arg_name, "` must be factors", call. = FALSE) } fs } forcats/R/anon.R0000644000176200001440000000132113626257051013176 0ustar liggesusers#' Anonymise factor levels #' #' Replaces factor levels with arbitrary numeric identifiers. Neither #' the values nor the order of the levels are preserved. #' #' @param f A factor. #' @param prefix A character prefix to insert in front of the random labels. #' @export #' @examples #' gss_cat$relig %>% fct_count() #' gss_cat$relig %>% fct_anon() %>% fct_count() #' gss_cat$relig %>% fct_anon("X") %>% fct_count() fct_anon <- function(f, prefix = "") { levels <- paste0(prefix, zero_pad(seq_len(nlevels(f)))) f <- lvls_revalue(f, sample(levels)) lvls_reorder(f, match(levels, levels(f))) } digits <- function(x) nchar(max(x, na.rm = TRUE)) zero_pad <- function(x) { sprintf(paste0("%0", digits(x), "d"), x) } forcats/R/fct_cross.R0000644000176200001440000000232313626252103014224 0ustar liggesusers#' Combine levels from two or more factors to create a new factor #' #' Computes a factor whose levels are all the combinations of the levels of the input factors. #' #' @param ... <[`dynamic-dots`][rlang::dyn-dots]> Additional factors #' or character vectors. #' @param sep A character string to separate the levels #' @param keep_empty If TRUE, keep combinations with no observations as levels #' @return The new factor #' #' @export #' @examples #' fruit <- factor(c("apple", "kiwi", "apple", "apple")) #' colour <- factor(c("green", "green", "red", "green")) #' eaten <- c("yes", "no", "yes", "no") #' fct_cross(fruit, colour) #' fct_cross(fruit, colour, eaten) #' fct_cross(fruit, colour, keep_empty = TRUE) fct_cross <- function(..., sep = ":", keep_empty = FALSE) { flist <- list2(...) if (length(flist) == 0) { return(factor()) } .data <- tibble::as_tibble(flist, .name_repair = "minimal") .data <- lapply(.data, check_factor) newf <- exec(paste, !!!.data, sep = sep) old_levels <- lapply(.data, levels) grid <- exec(expand.grid, old_levels) new_levels <- exec(paste, !!!grid, sep = sep) if (!keep_empty) { new_levels <- intersect(new_levels, newf) } factor(newf, levels = new_levels) } forcats/R/shuffle.R0000644000176200001440000000041413626051403013672 0ustar liggesusers#' Randomly permute factor levels #' #' @param f A factor (or character vector). #' @export #' @examples #' f <- factor(c("a", "b", "c")) #' fct_shuffle(f) #' fct_shuffle(f) fct_shuffle <- function(f) { f <- check_factor(f) lvls_reorder(f, sample(lvls_seq(f))) } forcats/R/lump.R0000644000176200001440000001527013764156637013243 0ustar liggesusers#' Lump together factor levels into "other" #' #' @description #' A family for lumping together levels that meet some criteria. #' * `fct_lump_min()`: lumps levels that appear fewer than `min` times. #' * `fct_lump_prop()`: lumps levels that appear in fewer `prop * n` times. #' * `fct_lump_n()` lumps all levels except for the `n` most frequent #' (or least frequent if `n < 0`) #' * `fct_lump_lowfreq()` lumps together the least frequent levels, ensuring #' that "other" is still the smallest level. #' #' `fct_lump()` exists primarily for historical reasons, as it automatically #' picks between these different methods depending on its arguments. #' We no longer recommend that you use it. #' #' @param f A factor (or character vector). #' @param n Positive `n` preserves the most common `n` values. #' Negative `n` preserves the least common `-n` values. #' It there are ties, you will get at least `abs(n)` values. #' @param prop Positive `prop` lumps values which do not appear at least #' `prop` of the time. Negative `prop` lumps values that #' do not appear at most `-prop` of the time. #' @param min Preserve levels that appear at least `min` number of times. #' @param w An optional numeric vector giving weights for frequency of #' each value (not level) in f. #' @param other_level Value of level used for "other" values. Always #' placed at end of levels. #' @param ties.method A character string specifying how ties are #' treated. See [rank()] for details. #' @export #' @seealso [fct_other()] to convert specified levels to other. #' @examples #' x <- factor(rep(LETTERS[1:9], times = c(40, 10, 5, 27, 1, 1, 1, 1, 1))) #' x %>% table() #' x %>% fct_lump_n(3) %>% table() #' x %>% fct_lump_prop(0.10) %>% table() #' x %>% fct_lump_min(5) %>% table() #' x %>% fct_lump_lowfreq() %>% table() #' #' x <- factor(letters[rpois(100, 5)]) #' x #' table(x) #' table(fct_lump_lowfreq(x)) #' #' # Use positive values to collapse the rarest #' fct_lump_n(x, n = 3) #' fct_lump_prop(x, prop = 0.1) #' #' # Use negative values to collapse the most common #' fct_lump_n(x, n = -3) #' fct_lump_prop(x, prop = -0.1) #' #' # Use weighted frequencies #' w <- c(rep(2, 50), rep(1, 50)) #' fct_lump_n(x, n = 5, w = w) #' #' # Use ties.method to control how tied factors are collapsed #' fct_lump_n(x, n = 6) #' fct_lump_n(x, n = 6, ties.method = "max") #' #' # Use fct_lump_min() to lump together all levels with fewer than `n` values #' table(fct_lump_min(x, min = 10)) #' table(fct_lump_min(x, min = 15)) fct_lump <- function(f, n, prop, w = NULL, other_level = "Other", ties.method = c("min", "average", "first", "last", "random", "max")) { ties.method <- match.arg(ties.method) check_calc_levels(f, w) if (missing(n) && missing(prop)) { fct_lump_lowfreq(f, other_level = other_level) } else if (missing(prop)) { fct_lump_n(f, n, w, other_level, ties.method) } else if (missing(n)) { fct_lump_prop(f, prop, w, other_level) } else { abort("Must supply only one of `n` and `prop`") } } #' @export #' @rdname fct_lump fct_lump_min <- function(f, min, w = NULL, other_level = "Other") { calcs <- check_calc_levels(f, w) f <- calcs$f if (!is.numeric(min) || length(min) != 1 || min < 0) { rlang::abort("`min` must be a positive number") } new_levels <- ifelse(calcs$count >= min, levels(f), other_level) if (other_level %in% new_levels) { f <- lvls_revalue(f, new_levels) fct_relevel(f, other_level, after = Inf) } else { f } } #' @export #' @rdname fct_lump fct_lump_prop <- function(f, prop, w = NULL, other_level = "Other") { calcs <- check_calc_levels(f, w) f <- calcs$f if (!is.numeric(prop) || length(prop) != 1) { rlang::abort("`prop` must be a number") } prop_n <- calcs$count / calcs$total if (prop < 0) { new_levels <- ifelse(prop_n <= -prop, levels(f), other_level) } else { new_levels <- ifelse(prop_n > prop, levels(f), other_level) } if (prop > 0 && sum(prop_n <= prop) <= 1) { # No lumping needed return(f) } if (other_level %in% new_levels) { f <- lvls_revalue(f, new_levels) fct_relevel(f, other_level, after = Inf) } else { f } } #' @export #' @rdname fct_lump fct_lump_n <- function(f, n, w = NULL, other_level = "Other", ties.method = c("min", "average", "first", "last", "random", "max")) { ties.method <- match.arg(ties.method) calcs <- check_calc_levels(f, w) f <- calcs$f if (!is.numeric(n) || length(n) != 1) { rlang::abort("`n` must be a number") } if (n < 0) { rank <- rank(calcs$count, ties.method = ties.method) n <- -n } else { rank <- rank(-calcs$count, ties.method = ties.method) } new_levels <- ifelse(rank <= n, levels(f), other_level) if (sum(rank > n) <= 1) { # No lumping needed return(f) } if (other_level %in% new_levels) { f <- lvls_revalue(f, new_levels) fct_relevel(f, other_level, after = Inf) } else { f } } #' @export #' @rdname fct_lump fct_lump_lowfreq <- function(f, other_level = "Other") { calcs <- check_calc_levels(f, NULL) f <- calcs$f new_levels <- ifelse(!in_smallest(calcs$count), levels(f), other_level) if (other_level %in% new_levels) { f <- lvls_revalue(f, new_levels) fct_relevel(f, other_level, after = Inf) } else { f } } check_calc_levels <- function(f, w = NULL) { f <- check_factor(f) w <- check_weights(w, length(f)) if (is.null(w)) { count <- as.vector(table(f)) total <- length(f) } else { count <- as.vector(tapply(w, f, FUN = sum)) total <- sum(w) } list(f = f, count = count, total = total) } # Lump together smallest groups, ensuring that the collective # "other" is still the smallest group. Assumes x is vector # of counts in descending order lump_cutoff <- function(x) { left <- sum(x) for (i in seq_along(x)) { # After group, there are this many left left <- left - x[i] if (x[i] > left) return(i + 1) } length(x) + 1 } # Given vector of counts, returns logical vector if in # smallest groups in_smallest <- function(x) { ord_x <- order(x, decreasing = TRUE) idx <- lump_cutoff(x[ord_x]) to_lump <- seq_along(x) >= idx # Undo initial ordering to_lump[order(ord_x)] } check_weights <- function(w, n = length(w)) { if (is.null(w)) { return(w) } if (!is.numeric(w)) { stop("`w` must be a numeric vector", call. = FALSE) } if (length(w) != n) { stop( "`w` must be the same length as `f` (", n, "), not length ", length(w), call. = FALSE ) } bad <- w < 0 | is.na(w) if (any(bad)) { stop( "All `w` must be non-negative and non-missing. Problems at positions: ", paste0(which(bad), collapse = ", "), call. = FALSE ) } w } forcats/R/drop.R0000644000176200001440000000152613626051403013207 0ustar liggesusers#' Drop unused levels #' #' Compared to `base::droplevels()`, does not drop `NA` levels that have values. #' #' @param f A factor (or character vector). #' @param only A character vector restricting the set of levels to be dropped. #' If supplied, only levels that have no entries and appear in this vector #' will be removed. #' @export #' @seealso [fct_expand()] to add additional levels to a factor. #' @examples #' f <- factor(c("a", "b"), levels = c("a", "b", "c")) #' f #' fct_drop(f) #' #' # Set only to restrict which levels to drop #' fct_drop(f, only = "a") #' fct_drop(f, only = "c") fct_drop <- function(f, only) { f <- check_factor(f) levels <- levels(f) count <- table(f) to_drop <- levels[count == 0] if (!missing(only)) { to_drop <- intersect(to_drop, only) } refactor(f, new_levels = setdiff(levels, to_drop)) } forcats/R/shift.R0000644000176200001440000000137013626051403013355 0ustar liggesusers#' Shift factor levels to left or right, wrapping around at end #' #' This is useful when the levels of an ordered factor are actually cyclical, #' with different conventions on the starting point. #' #' @param f A factor. #' @param n Positive values shift to the left; negative values shift to #' the right. #' @export #' @examples #' x <- factor( #' c("Mon", "Tue", "Wed"), #' levels = c("Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"), #' ordered = TRUE #' ) #' x #' fct_shift(x) #' fct_shift(x, 2) #' fct_shift(x, -1) fct_shift <- function(f, n = 1L) { lvls_reorder(f, shift(nlevels(f), n)) } shift <- function(m, n) { stopifnot(is.numeric(m), length(m) == 1L) stopifnot(is.numeric(n), length(n) == 1L) ((seq_len(m) - 1) + n) %% m + 1 } forcats/R/data.R0000644000176200001440000000113112754704614013156 0ustar liggesusers#' A sample of categorical variables from the General Social survey #' #' @source Downloaded from \url{https://gssdataexplorer.norc.org/}. #' @format #' \describe{ #' \item{year}{year of survey, 2000--2014} #' \item{age}{age. Maximum age truncated to 89.} #' \item{marital}{marital status} #' \item{race}{race} #' \item{rincome}{reported income} #' \item{partyid}{party affiliation} #' \item{relig}{religion} #' \item{denom}{denomination} #' \item{tvhours}{hours per day watching tv} #' } #' @examples #' gss_cat #' #' fct_count(gss_cat$relig) #' fct_count(fct_lump(gss_cat$relig)) "gss_cat" forcats/R/lvls.R0000644000176200001440000000607113626051403013223 0ustar liggesusers#' Low-level functions for manipulating levels #' #' `lvls_reorder` leaves values as they are, but changes the order. #' `lvls_revalue` changes the values of existing levels; there must #' be one new level for each old level. #' `lvls_expand` expands the set of levels; the new levels must #' include the old levels. #' #' These functions are less helpful than the higher-level `fct_` functions, #' but are safer than the very low-level manipulation of levels directly, #' because they are more specific, and hence can more carefully check their #' arguments. #' #' @param f A factor (or character vector). #' @param idx A integer index, with one integer for each existing level. #' @param new_levels A character vector of new levels. #' @param ordered A logical which determines the "ordered" status of the #' output factor. `NA` preserves the existing status of the factor. #' @name lvls #' @examples #' f <- factor(c("a", "b", "c")) #' lvls_reorder(f, 3:1) #' lvls_revalue(f, c("apple", "banana", "carrot")) #' lvls_expand(f, c("a", "b", "c", "d")) NULL #' @export #' @rdname lvls lvls_reorder <- function(f, idx, ordered = NA) { f <- check_factor(f) if (!is.numeric(idx)) { stop("`idx` must be numeric", call. = FALSE) } if (!setequal(idx, lvls_seq(f)) || length(idx) != nlevels(f)) { stop("`idx` must contain one integer for each level of `f`", call. = FALSE) } refactor(f, levels(f)[idx], ordered = ordered) } #' @export #' @rdname lvls lvls_revalue <- function(f, new_levels) { f <- check_factor(f) if (!is.character(new_levels)) { stop("`new_levels` must be a character vector", call. = FALSE) } if (length(new_levels) != nlevels(f)) { stop( "`new_levels` must be the same length as `levels(f)`: expected ", nlevels(f), " new levels, got ", length(new_levels), ".", call. = FALSE ) } if (anyDuplicated(new_levels)) { # Collapse levels, creating a new factor u_levels <- unique(new_levels) index <- match(new_levels, u_levels) out <- index[f] attributes(out) <- attributes(f) attr(out, "levels") <- u_levels out } else { attr(f, "levels") <- new_levels f } } #' @export #' @rdname lvls lvls_expand <- function(f, new_levels) { f <- check_factor(f) missing <- setdiff(levels(f), new_levels) if (length(missing) > 0) { stop( "Must include all existing levels. Missing: ", paste0(missing, collapse = ", "), call. = FALSE) } refactor(f, new_levels) } lvls_seq <- function(f) { seq_along(levels(f)) } refactor <- function(f, new_levels, ordered = NA) { if (is.na(ordered)) { ordered <- is.ordered(f) } new_f <- factor(f, levels = new_levels, exclude = NULL, ordered = ordered) attributes(new_f) <- utils::modifyList(attributes(f), attributes(new_f)) new_f } #' Find all levels in a list of factors #' #' @param fs A list of factors. #' @export #' @examples #' fs <- list(factor("a"), factor("b"), factor(c("a", "b"))) #' lvls_union(fs) lvls_union <- function(fs) { fs <- check_factor_list(fs) Reduce(function(x, y) union(x, levels(y)), fs, init = character()) } forcats/R/unique.R0000644000176200001440000000046113626252033013550 0ustar liggesusers#' Unique values of a factor #' #' @param f A factor. #' @export #' @examples #' f <- factor(letters[rpois(100, 10)]) #' #' unique(f) # in order of appearance #' fct_unique(f) # in order of levels fct_unique <- function(f) { factor(levels(f), levels(f), exclude = NULL, ordered = is.ordered(f)) } forcats/R/relevel.R0000644000176200001440000000421613764156755013723 0ustar liggesusers#' Reorder factor levels by hand #' #' This is a generalisation of [stats::relevel()] that allows you to move any #' number of levels to any location. #' #' @param .f A factor (or character vector). #' @param ... Either a function (or formula), or character levels. #' #' A function will be called with the current levels, and the return #' value (which must be a character vector) will be used to relevel the #' function. #' #' Any levels not mentioned will be left in their existing order, after the #' explicitly mentioned levels. Supports tidy dots. #' @param after Where should the new values be placed? #' @export #' @examples #' f <- factor(c("a", "b", "c", "d"), levels = c("b", "c", "d", "a")) #' fct_relevel(f) #' fct_relevel(f, "a") #' fct_relevel(f, "b", "a") #' #' # Move to the third position #' fct_relevel(f, "a", after = 2) #' #' # Relevel to the end #' fct_relevel(f, "a", after = Inf) #' fct_relevel(f, "a", after = 3) #' #' # Relevel with a function #' fct_relevel(f, sort) #' fct_relevel(f, sample) #' fct_relevel(f, rev) #' #' # Using 'Inf' allows you to relevel to the end when the number #' # of levels is unknown or variable (e.g. vectorised operations) #' df <- forcats::gss_cat[, c("rincome", "denom")] #' lapply(df, levels) #' #' df2 <- lapply(df, fct_relevel, "Don't know", after = Inf) #' lapply(df2, levels) #' #' # You'll get a warning if the levels don't exist #' fct_relevel(f, "e") fct_relevel <- function(.f, ..., after = 0L) { f <- check_factor(.f) old_levels <- levels(f) if (dots_n(...) == 1L && (is.function(..1) || is_formula(..1))) { fun <- as_function(..1) first_levels <- fun(old_levels) if (!is.character(first_levels)) { stop("Re-leveling function must return character vector", call. = FALSE) } } else { first_levels <- chr(...) } unknown <- setdiff(first_levels, old_levels) if (length(unknown) > 0) { warning("Unknown levels in `f`: ", paste(unknown, collapse = ", "), call. = FALSE) first_levels <- intersect(first_levels, old_levels) } new_levels <- append(setdiff(old_levels, first_levels), first_levels, after = after) lvls_reorder(f, match(new_levels, old_levels)) } forcats/R/relabel.R0000644000176200001440000000231313626252103013644 0ustar liggesusers#' Automatically relabel factor levels, collapse as necessary #' #' @param .f A factor (or character vector). #' @param .fun A function to be applied to each level. Must accept one #' character argument and return a character vector of the same length as #' its input. #' #' You can also use `~` to create as shorthand (in the style of purrr). #' `~ paste(., "x")` is equivalent to `function(.) paste(., "x")` #' @param ... Additional arguments to `fun`. #' @export #' @examples #' gss_cat$partyid %>% fct_count() #' gss_cat$partyid %>% fct_relabel(~ gsub(",", ", ", .x)) %>% fct_count() #' #' convert_income <- function(x) { #' regex <- "^(?:Lt |)[$]([0-9]+).*$" #' is_range <- grepl(regex, x) #' num_income <- as.numeric(gsub(regex, "\\1", x[is_range])) #' num_income <- trunc(num_income / 5000) * 5000 #' x[is_range] <- paste0("Gt $", num_income) #' x #' } #' fct_count(gss_cat$rincome) #' convert_income(levels(gss_cat$rincome)) #' rincome2 <- fct_relabel(gss_cat$rincome, convert_income) #' fct_count(rincome2) fct_relabel <- function(.f, .fun, ...) { f <- check_factor(.f) .fun <- as_function(.fun) old_levels <- levels(f) new_levels <- .fun(old_levels, ...) lvls_revalue(f, new_levels) } forcats/R/explicit_na.R0000644000176200001440000000147413626252103014544 0ustar liggesusers#' Make missing values explicit #' #' This gives missing values an explicit factor level, ensuring that they #' appear in summaries and on plots. #' #' @param f A factor (or character vector). #' @param na_level Level to use for missing values: this is what NAs will be changed to. #' @export #' @examples #' f1 <- factor(c("a", "a", NA, NA, "a", "b", NA, "c", "a", "c", "b")) #' fct_count(f1) #' #' f2 <- fct_explicit_na(f1) #' fct_count(f2) fct_explicit_na <- function(f, na_level = "(Missing)") { f <- check_factor(f) is_missing <- is.na(f) is_missing_level <- is.na(levels(f)) if (any(is_missing)) { f <- fct_expand(f, na_level) f[is_missing] <- na_level f } else if (any(is_missing_level)) { levs <- levels(f) levs[is.na(levs)] <- na_level lvls_revalue(f, levs) } else { f } } forcats/R/match.R0000644000176200001440000000206713626051403013340 0ustar liggesusers#' Test for presence of levels in a factor #' #' Do any of `lvls` occur in `f`? Compared to [%in%], this function validates #' `lvls` to ensure that they're actually present in `f`. In other words, #' `x %in% "not present"` will return `FALSE`, but `fct_match(x, "not present")` #' will throw an error. #' #' @rdname fct_match #' @param f A factor (or character vector). #' @param lvls A character vector specifying levels to look for. #' @return A logical vector #' @export #' @examples #' table(fct_match(gss_cat$marital, c("Married", "Divorced"))) #' #' # Compare to %in%, misspelled levels throw an error #' table(gss_cat$marital %in% c("Maried", "Davorced")) #' \dontrun{ #' table(fct_match(gss_cat$marital, c("Maried", "Davorced"))) #' } #' fct_match <- function(f, lvls) { f <- check_factor(f) bad_lvls <- setdiff(lvls, levels(f)) bad_lvls <- bad_lvls[!is.na(bad_lvls)] if (length(bad_lvls) > 0) { stop( "Levels not present in factor: ", paste0(encodeString(bad_lvls, quote = '"'), collapse = ", "), call. = FALSE ) } f %in% lvls } forcats/R/forcats-package.R0000644000176200001440000000006213626252103015267 0ustar liggesusers#' @keywords internal #' @import rlang "_PACKAGE" forcats/R/as_factor.R0000644000176200001440000000252413626461710014211 0ustar liggesusers#' Convert input to a factor #' #' Compared to base R, when `x` is a character, this function creates #' levels in the order in which they appear, which will be the same on every #' platform. (Base R sorts in the current locale which can vary from place #' to place.) When `x` is numeric, the ordering is based on the numeric #' value and consistent with base R. #' #' This is a generic function. #' #' @param x Object to coerce to a factor. #' @param ... Other arguments passed down to method. #' @export #' @examples #' # Character object #' x <- c("a", "z", "g") #' as_factor(x) #' as.factor(x) #' #' # Character object containing numbers #' y <- c("1.1", "11", "2.2", "22") #' as_factor(y) #' as.factor(y) #' #' # Numeric object #' z <- as.numeric(y) #' as_factor(z) #' as.factor(z) as_factor <- function(x, ...) { ellipsis::check_dots_used() UseMethod("as_factor") } #' @rdname as_factor #' @export as_factor.factor <- function(x, ...) { x } #' @rdname as_factor #' @export as_factor.character <- function(x, ...) { # Preserve label for future haven compatibility structure( fct_inorder(x), label = attr(x, "label", exact = TRUE) ) } #' @rdname as_factor #' @export as_factor.numeric <- function(x, ...) { factor(x) } #' @rdname as_factor #' @export as_factor.logical <- function(x, ...) { factor(x, levels = c("FALSE", "TRUE")) } forcats/R/recode.R0000644000176200001440000000415413764157242013517 0ustar liggesusers#' Change factor levels by hand #' #' @param .f A factor (or character vector). #' @param ... <[`dynamic-dots`][rlang::dyn-dots]> A sequence of named character #' vectors where the name gives the new level, and the value gives the old #' level. Levels not otherwise mentioned will be left as is. Levels can #' be removed by naming them `NULL`. #' @export #' @examples #' x <- factor(c("apple", "bear", "banana", "dear")) #' fct_recode(x, fruit = "apple", fruit = "banana") #' #' # If you make a mistake you'll get a warning #' fct_recode(x, fruit = "apple", fruit = "bananana") #' #' # If you name the level NULL it will be removed #' fct_recode(x, NULL = "apple", fruit = "banana") #' #' # Wrap the left hand side in quotes if it contains special variables #' fct_recode(x, "an apple" = "apple", "a bear" = "bear") #' #' # When passing a named vector to rename levels use !!! to splice #' x <- factor(c("apple", "bear", "banana", "dear")) #' levels <- c(fruit = "apple", fruit = "banana") #' fct_recode(x, !!!levels) fct_recode <- function(.f, ...) { f <- check_factor(.f) new_levels <- check_recode_levels(...) # Remove any named NULL and finish if all NULLs nulls <- names(new_levels) == "NULL" if (any(nulls)) { f <- factor(f, levels = setdiff(levels(f), new_levels[nulls])) new_levels <- new_levels[!nulls] } # Match old levels with new levels old_levels <- levels(f) idx <- match(new_levels, old_levels) # Handle levels that don't exist if (any(is.na(idx))) { bad <- new_levels[is.na(idx)] warning("Unknown levels in `f`: ", paste(bad, collapse = ", "), call. = FALSE) new_levels <- new_levels[!is.na(idx)] idx <- idx[!is.na(idx)] } old_levels[idx] <- names(new_levels) lvls_revalue(f, old_levels) } check_recode_levels <- function(...) { levels <- rlang::list2(...) is_ok <- function(x) is.character(x) && length(x) == 1 ok <- vapply(levels, is_ok, logical(1)) if (!all(ok)) { stop( "Each input to fct_recode must be a single named string. ", "Problems at positions: ", paste0(which(!ok), collapse = ", "), call. = FALSE ) } unlist(levels) } forcats/R/collapse.R0000644000176200001440000000274613626261320014053 0ustar liggesusers#' Collapse factor levels into manually defined groups #' #' @param .f A factor (or character vector). #' @param ... <[`dynamic-dots`][rlang::dyn-dots]> A series of named character vectors. The levels in #' each vector will be replaced with the name. #' @inheritParams fct_other #' @param group_other Deprecated. Replace all levels not named in `...` with "Other"? #' @export #' @examples #' fct_count(gss_cat$partyid) #' #' partyid2 <- fct_collapse(gss_cat$partyid, #' missing = c("No answer", "Don't know"), #' other = "Other party", #' rep = c("Strong republican", "Not str republican"), #' ind = c("Ind,near rep", "Independent", "Ind,near dem"), #' dem = c("Not str democrat", "Strong democrat") #' ) #' fct_count(partyid2) fct_collapse <- function(.f, ..., other_level = NULL, group_other = "DEPRECATED") { if (!missing(group_other)) { warning("`group_other` is deprecated. Please use `other_level` instead") if (isTRUE(group_other) && is.null(other_level)) { other_level <- "Other" } } new <- rlang::list2(...) levs <- as.list(unlist(new, use.names = FALSE)) if (!is.null(other_level)){ f <- check_factor(.f) levels <- levels(f) new[[other_level]] <- levels[!levels %in% levs] levs <- c(levs, new[[other_level]]) } names(levs) <- names(new)[rep(seq_along(new), vapply(new, length, integer(1)))] out <- fct_recode(.f, !!!levs) if (any(levels(out) == other_level)){ fct_relevel(out, other_level, after = Inf) } else return(out) } forcats/R/reorder.R0000644000176200001440000001051713626262434013715 0ustar liggesusers#' Reorder factor levels by sorting along another variable #' #' `fct_reorder()` is useful for 1d displays where the factor is mapped to #' position; `fct_reorder2()` for 2d displays where the factor is mapped to #' a non-position aesthetic. `last2()` and `first2()` are helpers for `fct_reorder2()`; #' `last2()` finds the last value of `y` when sorted by `x`; `first2()` finds the first value. #' #' @param .f A factor (or character vector). #' @param .x,.y The levels of `f` are reordered so that the values #' of `.fun(.x)` (for `fct_reorder()`) and `fun(.x, .y)` (for `fct_reorder2()`) #' are in ascending order. #' @param .fun n summary function. It should take one vector for #' `fct_reorder`, and two vectors for `fct_reorder2`, and return a single #' value. #' @param ... Other arguments passed on to `.fun`. A common argument is #' `na.rm = TRUE`. #' @param .desc Order in descending order? Note the default is different #' between `fct_reorder` and `fct_reorder2`, in order to #' match the default ordering of factors in the legend. #' @importFrom stats median #' @export #' @examples #' df <- tibble::tribble( #' ~color, ~a, ~b, #' "blue", 1, 2, #' "green", 6, 2, #' "purple", 3, 3, #' "red", 2, 3, #' "yellow", 5, 1 #' ) #' df$color <- factor(df$color) #' fct_reorder(df$color, df$a, min) #' fct_reorder2(df$color, df$a, df$b) #' #' boxplot(Sepal.Width ~ Species, data = iris) #' boxplot(Sepal.Width ~ fct_reorder(Species, Sepal.Width), data = iris) #' boxplot(Sepal.Width ~ fct_reorder(Species, Sepal.Width, .desc = TRUE), data = iris) #' #' chks <- subset(ChickWeight, as.integer(Chick) < 10) #' chks <- transform(chks, Chick = fct_shuffle(Chick)) #' #' if (require("ggplot2")) { #' ggplot(chks, aes(Time, weight, colour = Chick)) + #' geom_point() + #' geom_line() #' #' # Note that lines match order in legend #' ggplot(chks, aes(Time, weight, colour = fct_reorder2(Chick, Time, weight))) + #' geom_point() + #' geom_line() + #' labs(colour = "Chick") #' } fct_reorder <- function(.f, .x, .fun = median, ..., .desc = FALSE) { f <- check_factor(.f) stopifnot(length(f) == length(.x)) ellipsis::check_dots_used() summary <- tapply(.x, .f, .fun, ...) # This is a bit of a weak test, but should detect the most common case # where `.fun` returns multiple values. if (is.list(summary)) { stop("`fun` must return a single value per group", call. = FALSE) } lvls_reorder(f, order(summary, decreasing = .desc)) } #' @export #' @rdname fct_reorder fct_reorder2 <- function(.f, .x, .y, .fun = last2, ..., .desc = TRUE) { f <- check_factor(.f) stopifnot(length(f) == length(.x), length(.x) == length(.y)) ellipsis::check_dots_used() summary <- tapply(seq_along(.x), f, function(i) .fun(.x[i], .y[i], ...)) if (is.list(summary)) { stop("`fun` must return a single value per group", call. = FALSE) } lvls_reorder(.f, order(summary, decreasing = .desc)) } #' @export #' @rdname fct_reorder last2 <- function(.x, .y) { .y[order(.x, na.last = FALSE)][length(.y)] } #' @export #' @rdname fct_reorder first2 <- function(.x, .y) { .y[order(.x)][1] } #' Reorder factor levels by first appearance, frequency, or numeric order #' #' This family of functions changes only the order of the levels. #' * `fct_inorder()`: by the order in which they first appear. #' * `fct_infreq()`: by number of observations with each level (largest first) #' * `fct_inseq()`: by numeric value of level. #' #' @inheritParams lvls_reorder #' @param f A factor #' @export #' @examples #' f <- factor(c("b", "b", "a", "c", "c", "c")) #' f #' fct_inorder(f) #' fct_infreq(f) #' #' f <- factor(1:3, levels = c("3", "2", "1")) #' f #' fct_inseq(f) fct_inorder <- function(f, ordered = NA) { f <- check_factor(f) idx <- as.integer(f)[!duplicated(f)] idx <- idx[!is.na(idx)] lvls_reorder(f, idx, ordered = ordered) } #' @export #' @rdname fct_inorder fct_infreq <- function(f, ordered = NA) { f <- check_factor(f) lvls_reorder(f, order(table(f), decreasing = TRUE), ordered = ordered) } #' @export #' @rdname fct_inorder fct_inseq <- function(f, ordered = NA) { f <- check_factor(f) num_levels <- suppressWarnings(as.numeric(levels(f))) if (all(is.na(num_levels))) { stop("At least one existing level must be coercible to numeric.", call. = FALSE) } lvls_reorder(f, order(num_levels), ordered = ordered) } forcats/R/expand.R0000644000176200001440000000102413626252103013513 0ustar liggesusers#' Add additional levels to a factor #' #' @param f A factor (or character vector). #' @param ... Additional levels to add to the factor. Levels that already #' exist will be silently ignored. #' @export #' @seealso [fct_drop()] to drop unused factor levels. #' @examples #' f <- factor(sample(letters[1:3], 20, replace = TRUE)) #' f #' fct_expand(f, "d", "e", "f") #' fct_expand(f, letters[1:6]) fct_expand <- function(f, ...) { f <- check_factor(f) new_levels <- chr(...) lvls_expand(f, union(levels(f), new_levels)) } forcats/R/other.R0000644000176200001440000000175113626051403013364 0ustar liggesusers#' Replace levels with "other" #' #' @inheritParams fct_lump #' @param keep,drop Pick one of `keep` and `drop`: #' * `keep` will preserve listed levels, replacing all others with #' `other_level`. #' * `drop` will replace listed levels with `other_level`, keeping all #' as is. #' @seealso [fct_lump()] to automatically convert the rarest (or most #' common) levels to "other". #' @export #' @examples #' x <- factor(rep(LETTERS[1:9], times = c(40, 10, 5, 27, 1, 1, 1, 1, 1))) #' #' fct_other(x, keep = c("A", "B")) #' fct_other(x, drop = c("A", "B")) fct_other <- function(f, keep, drop, other_level = "Other") { f <- check_factor(f) if (!xor(missing(keep), missing(drop))) { stop("Must supply exactly one of `keep` and `drop`", call. = FALSE) } levels <- levels(f) if (!missing(keep)) { levels[!levels %in% keep] <- other_level } else { levels[levels %in% drop] <- other_level } f <- lvls_revalue(f, levels) fct_relevel(f, other_level, after = Inf) } forcats/R/c.R0000644000176200001440000000233313626252103012462 0ustar liggesusers#' Concatenate factors, combining levels #' #' This is a useful way of patching together factors from multiple sources #' that really should have the same levels but don't. #' #' @param ... <[`dynamic-dots`][rlang::dyn-dots]> Individual #' factors. Uses tidy dots, so you can splice in a list of factors #' with `!!!`. #' @export #' @examples #' fa <- factor("a") #' fb <- factor("b") #' fab <- factor(c("a", "b")) #' #' c(fa, fb, fab) #' fct_c(fa, fb, fab) #' #' # You can also pass a list of factors with !!! #' fs <- list(fa, fb, fab) #' fct_c(!!!fs) fct_c <- function(...) { fs <- rlang::list2(...) fs <- check_factor_list(fs, "...") if (length(fs) == 0) { return(factor()) } levels <- lvls_union(fs) all <- unlist(fct_unify(fs, levels), use.names = FALSE) factor(all, levels = levels, exclude = NULL) } #' Unify the levels in a list of factors #' #' @param fs A list of factors #' @param levels Set of levels to apply to every factor. Default to #' union of all factor levels #' @export #' @examples #' fs <- list(factor("a"), factor("b"), factor(c("a", "b"))) #' fct_unify(fs) fct_unify <- function(fs, levels = lvls_union(fs)) { fs <- check_factor_list(fs) lapply(fs, lvls_expand, new_levels = levels) } forcats/NEWS.md0000644000176200001440000001210314004275144013007 0ustar liggesusers# forcats 0.5.1 * Re-license as MIT (#277). * `fct_lump_n()` no longer uses a partial argument name (@malcolmbarrett, #276). # forcats 0.5.0 * `as_factor()` gains a logical method that always returns a factor with levels "FALSE" and "TRUE" (#185). * `fct_c()`, `fct_collapse()` and `fct_recode()` are now explicitly documented as using [dynamic dots](https://rlang.r-lib.org/reference/dyn-dots.html) (@labouz, #234). * `fct_collapse()` now accepts a `other_level` argument, to allow a user-specified `Other` level (@gtm19, #194). It now correctly collapses factors when `other_level` is not `NULL` (#172), and makes `"Other"` the last level (#202) (@gtm19, #172 & #202) * `fct_count()` no longer converts implicit NAs into explicit NAs (#151). * `fct_inseq()` behaves more robustly when factor levels aren't all numbers (#221). * `fct_lump()` has been split up into three new functions: `fct_lump_prop()`, `fct_lump_n()`, and `fct_lump_lowfreq()`. (@jonocarroll, #167, #142). All `fct_lump_()` functions check their inputs more carefully (@robinson_es, #169) * `fct_reorder2()` gains a helper function `first2()`, that sorts `.y` by the first value of `.x` (@jtr13). # forcats 0.4.0 ## New features * `fct_collapse()` gains a `group_other` argument to allow you to group all un-named levels into `"Other"`. (#100, @AmeliaMN) * `fct_cross()` creates a new factor containing the combined levels from two or more input factors, similar to `base::interaction` (@tslumley, #136) * `fct_inseq()` reorders labels in numeric order, if possible (#145, @kbodwin). * `fct_lump_min()` preserves levels that appear at least `min` times (can also be used with the `w` weighted argument) (@robinsones, #142). * `fct_match()` performs validated matching, providing a safer alternative to `f %in% c("x", "y")` which silently returns `FALSE` if `"x"` or `"y"` are not levels of `f` (e.g. because of a typo) (#126, @jonocarroll). * `fct_relevel()` can now level factors using a function that is passed the current levels (#117). * `as_factor()` now has a numeric method. By default, orders factors in numeric order, unlike the other methods which default to order of appearance. (#145, @kbodwin) ## Minor bug fixes and improvements * `fct_count()` gains a parameter to also compute the proportion (@zhiiiyang, #146). * `fct_lump()` now does not change the label if no lumping occurs (@zhiiiyang, #130). * `fct_relabel()` now accepts character input. * `fct_reorder()` and `fct_reorder2()` no longer require that the summary function return a numeric vector of length 1; instead it can return any orderable vector of length 1 (#147). * `fct_reorder()`, `fct_reorder2()` and `as_factor()` now use the ellipsis package to warn if you pass in named components to `...` (#174). # forcats 0.3.0 ## API changes * `fct_c()` now requires explicit splicing with `!!!` if you have a list of factors that you want to combine. This is consistent with an emerging standards for handling `...` throughout the tidyverse. * `fct_reorder()` and `fct_reorder2()` have renamed `fun` to `.fun` to avoid spurious matching of named arguments. ## New features * All functions that take `...` use "tidy" dots: this means that you use can `!!!` to splice in a list of values, and trailing empty arguments are automatically removed. Additionally, all other arguments gain a `.` prefix in order to avoid unhelpful matching of named arguments (#110). * `fct_lump()` gains `w` argument (#70, @wilkox) to weight value frequencies before lumping them together (#68). ## Improvements to NA handling * `as_factor()` and `fct_inorder()` accept NA levels (#98). * `fct_explicit_na()` also replaces NAs encoded in levels. * `fct_lump()` correctly accounts for `NA` values in input (#41) * `lvls_revalue()` preserves NA levels. ## Minor improvements and bug fixes * Test coverage increased from 80% to 99%. * `fct_drop()` now preserves attributes (#83). * `fct_expand()` and `lvls_expand()` now also take character vectors (#99). * `fct_relabel()` now accepts objects coercible to functions by `rlang::as_function` (#91, @alistaire47) # forcats 0.2.0 ## New functions * `as_factor()` which works like `as.factor()` but orders levels by appearance to avoid differences between locales (#39). * `fct_other()` makes it easier to convert selected levels to "other" (#40) * `fct_relabel()` allows programmatic relabeling of levels (#50, @krlmlr). ## Minor improvements and bug fixes * `fct_c()` can take either a list of factors or individual factors (#42). * `fct_drop()` gains `only` argument to restrict which levels are dropped (#69) and no longer adds `NA` level if not present (#52). * `fct_recode()` is now checks that each new value is of length 1 (#56). * `fct_relevel()` gains `after` argument so you can also move levels to the end (or any other position you like) (#29). * `lvls_reorder()`, `fct_inorder()`, and `fct_infreq()` gain an `ordered` argument, allowing you to override the existing "ordered" status (#54). # forcats 0.1.1 * Minor fixes for R CMD check * Add package docs forcats/MD50000644000176200001440000001107614004341752012230 0ustar liggesusers983fd92fcc3d571a2d5630dde33ccedf *DESCRIPTION 500bcbd26c47066e09614bf631a00918 *LICENSE 780cd0cdc58864922d71e9c010211739 *NAMESPACE 9c3555dc1526be6e4468cea5f6755d5d *NEWS.md cf979f222168935b98e6f459d69194e4 *R/anon.R dcc63b5bf2c0954cb34b993ba072e297 *R/as_factor.R e6d789c894ecef380a931e1d5ebd81e5 *R/c.R 73280fb9816b7ea044ef3e78e210f0ee *R/collapse.R d8e8d579a2ec5210c9a4a996091f6f71 *R/count.R 9b8c9f934b7a5c9193cc8f197bbe9b2e *R/data.R 83518de9a1dfb35452653ef137eed507 *R/drop.R 5e3026d9ff261cecbc5f425228fe54fb *R/expand.R e52c94afc8327e95ae50e52d69a3d033 *R/explicit_na.R a8e619633853b9a42871596ffbbe94ac *R/fct_cross.R 0f95d2e1d6ec424ddfbffff4a4c3219d *R/forcats-package.R e9094fe6a0dcbfcb840ede2c5b8e1103 *R/lump.R cd0818ab06b278ddc2a38b5a3eaab4d9 *R/lvls.R f701fe9a2e7e2ccd79d26ed0a76a251a *R/match.R 4e286d23ca44d4d51ba7e397d133f331 *R/other.R ff6cb2f766a35e36a8a120167fec2549 *R/recode.R 4bd623be18ab9156e9efdd29420aa0d9 *R/relabel.R e772aeb904377754fa635cf506d8b338 *R/relevel.R 680bf5f7dba595608121037a8af6c7d6 *R/reorder.R 2513b5d4ddb3af53f57f9ef368200112 *R/rev.R 6a741a6fb62aa246f865f06dd172de1c *R/shift.R 9aebfd5ecc427de639e076a022cb0a53 *R/shuffle.R ee5201d1d40e6b81689639f92ae9fa2d *R/unique.R c52b4d9474163408c423eb70f81192aa *R/utils.R d87077a46593582e9c43c7b27735253a *README.md 28eb22be0d650707e2b88afc09bc0d31 *build/vignette.rds a6984b4f6c2e70deebeca86c7b3d76ea *data/gss_cat.rda ea759ae100f92e20d17c15daef35c86f *inst/doc/forcats.R dc8f167e825729287fe0728feb22ad27 *inst/doc/forcats.Rmd 467c1b545fd4f0d6f366fcc34046ad56 *inst/doc/forcats.html b7ee1e2072b474ba8ea48f495361cc2f *man/as_factor.Rd 4334dc56c28f8b2cb0a1980e696da92f *man/fct_anon.Rd e10a6e7d3527d4948d37dddcdeaeb977 *man/fct_c.Rd 73ac4d6b4fa9232f4baed433303f4e1f *man/fct_collapse.Rd f060da2e6dff2914fb1bc54504ca4a67 *man/fct_count.Rd bb79748e3806dc9e3a20d1bd32f76310 *man/fct_cross.Rd c42f9c956059fefbefe126474e29a233 *man/fct_drop.Rd 0a40a6cf33b7d3b10c10ec0ec75a8ac1 *man/fct_expand.Rd 6aa490c3eb3581fc75ad34f110195a3b *man/fct_explicit_na.Rd 74b0d745dd5fb68b7fbd704c8268323c *man/fct_inorder.Rd ad30109a59ec774059c975a59350721e *man/fct_lump.Rd 4ef733cedba6eda64440603d8ee6d8c9 *man/fct_match.Rd 7fe8a819595d5bd5ac505fabbd376c52 *man/fct_other.Rd d86392e9a40f6ce7c5fdfeca710fcf99 *man/fct_recode.Rd a8e656d7bb297da6570fc4e71d0ed371 *man/fct_relabel.Rd 7de16d981fa0f6512cb4a0cadc554d5f *man/fct_relevel.Rd eed6b04c5f3e8e65d12f1c4c974ced4e *man/fct_reorder.Rd cf766cb9ca0d896a0955c0ad191b1e78 *man/fct_rev.Rd fa07b6aa7ca3c5c73b573f497dc5e68e *man/fct_shift.Rd e37efbf13b7923999c1412bcb819a57b *man/fct_shuffle.Rd 9122ce4e63cfe89aaed8a006a6748c1d *man/fct_unify.Rd 29e25af605ce7b8242ed2bcaad84428f *man/fct_unique.Rd 97e4bac3f9f1f57ec24faa501d478125 *man/figures/README-ordered-plot-1.png 37d177544117670d5cdedafc1f931282 *man/figures/README-unordered-plot-1.png 3252fda93a16a69b6deb795c4866b7cb *man/figures/logo.png c1b0f984c1ec4016b2d7d79e29b87e91 *man/forcats-package.Rd 3b96c4cdca0257f6c8e68e7b2bd1e625 *man/gss_cat.Rd 679f67140aa7a12ffa8e2644324a1231 *man/lvls.Rd 50ed89e2798ad529ca69dad8d85851dd *man/lvls_union.Rd 0f020b37daf27c2fd4c78c574285ef1b *man/pipe.Rd 7b0f13301043822509977d02384cb6e9 *tests/testthat.R b7276ce56a13629f4741508087849bf6 *tests/testthat/helper-lump.R d54da72338a1e6edf9b7ea1c4b77309a *tests/testthat/test-anon.R 69349fd99833900992a64c0bf7fc9418 *tests/testthat/test-as_factor.R 5bbbfb537652dc46d3acf0c70510dd2e *tests/testthat/test-collapse.R 3bedb1b3b47997ed94ab427061e2419b *tests/testthat/test-count.R 94ced03ac637bcd6e4da7ed74a6db9cc *tests/testthat/test-explicit_na.R abc6b12c9ac566a532b368df371303cb *tests/testthat/test-fct_c.R 2eb0c582349f710bd04ba565fad4dc4a *tests/testthat/test-fct_cross.R 2da1b3ace9cf79139782fb3cb5fcf737 *tests/testthat/test-fct_drop.R 344b49d2a85a645b43f973e23022e8ef *tests/testthat/test-fct_other.R 73c6685513fd25b80919c7211a0bee93 *tests/testthat/test-fct_recode.R 6e116836c37935c9daf6fc4ca778c93e *tests/testthat/test-fct_relabel.R 6b2451dd2ae4f763ad26d609cede88b2 *tests/testthat/test-lump.R 8bf75dec2477f0bcb482f57cdbcb1c71 *tests/testthat/test-lvls.R e8e369f72b8bd87b6c53c3a881e79e04 *tests/testthat/test-lvls_reorder.R 52c2da070828a4ba816de925327a66ec *tests/testthat/test-match.R 7d92bdc6e200eb78789528d9c695e93e *tests/testthat/test-relevel.R 549c1eb0647f3340623e4c8950b6b81f *tests/testthat/test-reorder.R 371dc92dbf14f009077b997f00b297cb *tests/testthat/test-rev.R a0df68c919a132b10db11d2d2a37fa9c *tests/testthat/test-shift.R 9804486a2ed35c047035d010ea9b99cc *tests/testthat/test-shuffle.R ace13f92d674afbc6a66b69ab55e2db8 *tests/testthat/test-utils.R dc8f167e825729287fe0728feb22ad27 *vignettes/forcats.Rmd forcats/inst/0000755000176200001440000000000014004327012012661 5ustar liggesusersforcats/inst/doc/0000755000176200001440000000000014004327012013426 5ustar liggesusersforcats/inst/doc/forcats.R0000644000176200001440000000471314004327012015217 0ustar liggesusers## ----setup, include = FALSE--------------------------------------------------- knitr::opts_chunk$set( collapse = TRUE, comment = "#>" ) ## ----message = FALSE---------------------------------------------------------- library(dplyr) library(ggplot2) library(forcats) ## ----initial-plot------------------------------------------------------------- ggplot(starwars, aes(x = hair_color)) + geom_bar() + coord_flip() ## ----fct-infreq-hair---------------------------------------------------------- ggplot(starwars, aes(x = fct_infreq(hair_color))) + geom_bar() + coord_flip() ## ----------------------------------------------------------------------------- starwars %>% count(skin_color, sort = TRUE) ## ----------------------------------------------------------------------------- starwars %>% mutate(skin_color = fct_lump(skin_color, n = 5)) %>% count(skin_color, sort = TRUE) ## ----------------------------------------------------------------------------- starwars %>% mutate(skin_color = fct_lump(skin_color, prop = .1)) %>% count(skin_color, sort = TRUE) ## ----------------------------------------------------------------------------- starwars %>% mutate(skin_color = fct_lump(skin_color, prop = .1, other_level = "extra")) %>% count(skin_color, sort = TRUE) ## ----fct-lump-mean------------------------------------------------------------ avg_mass_eye_color <- starwars %>% mutate(eye_color = fct_lump(eye_color, n = 6)) %>% group_by(eye_color) %>% summarise(mean_mass = mean(mass, na.rm = TRUE)) avg_mass_eye_color ## ----fct-reorder-------------------------------------------------------------- avg_mass_eye_color %>% mutate(eye_color = fct_reorder(eye_color, mean_mass)) %>% ggplot(aes(x = eye_color, y = mean_mass)) + geom_col() ## ----------------------------------------------------------------------------- gss_cat %>% count(rincome) ## ----------------------------------------------------------------------------- levels(gss_cat$rincome) ## ----------------------------------------------------------------------------- reshuffled_income <- gss_cat$rincome %>% fct_shuffle() levels(reshuffled_income) ## ----------------------------------------------------------------------------- fct_relevel(reshuffled_income, c("Lt $1000", "$1000 to 2999")) %>% levels() ## ----------------------------------------------------------------------------- fct_relevel(reshuffled_income, c("Lt $1000", "$1000 to 2999"), after = 1) %>% levels() forcats/inst/doc/forcats.Rmd0000644000176200001440000001214514004267612015547 0ustar liggesusers--- title: "Introduction to forcats" author: "Emily Robinson" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Introduction to forcats} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r setup, include = FALSE} knitr::opts_chunk$set( collapse = TRUE, comment = "#>" ) ``` The goal of the __forcats__ package is to provide a suite of useful tools that solve common problems with factors. Factors are useful when you have categorical data, variables that have a fixed and known set of values, and when you want to display character vectors in non-alphabetical order. If you want to learn more, the best place to start is the [chapter on factors](https://r4ds.had.co.nz/factors.html) in R for Data Science. ## Ordering by frequency ```{r message = FALSE} library(dplyr) library(ggplot2) library(forcats) ``` Let's try answering the question, "what are the most common hair colors of star wars characters?" Let's start off by making a bar plot: ```{r initial-plot} ggplot(starwars, aes(x = hair_color)) + geom_bar() + coord_flip() ``` That's okay, but it would be more helpful the graph was ordered by count. This is a case of an **unordered** categorical variable where we want it ordered by its frequency. To do so, we can use the function `fct_infreq()`: ```{r fct-infreq-hair} ggplot(starwars, aes(x = fct_infreq(hair_color))) + geom_bar() + coord_flip() ``` Note that `fct_infreq()` it automatically puts NA at the top, even though that doesn't have the smallest number of entries. ## Combining levels Let's take a look at skin color now: ```{r} starwars %>% count(skin_color, sort = TRUE) ``` We see that there's 31 different skin colors - if we want to make a plot this would be way too many to display! Let's reduce it to only be the top 5. We can use `fct_lump()` to "lump" all the infrequent colors into one factor, "other." The argument `n` is the number of levels we want to keep. ```{r} starwars %>% mutate(skin_color = fct_lump(skin_color, n = 5)) %>% count(skin_color, sort = TRUE) ``` We could also have used `prop` instead, which keeps all the levels that appear at least `prop` of the time. For example, let's keep skin colors that at least 10% of the characters have: ```{r} starwars %>% mutate(skin_color = fct_lump(skin_color, prop = .1)) %>% count(skin_color, sort = TRUE) ``` Only light and fair remain; everything else is other. If you wanted to call it something than "other", you can change it with the argument `other_level`: ```{r} starwars %>% mutate(skin_color = fct_lump(skin_color, prop = .1, other_level = "extra")) %>% count(skin_color, sort = TRUE) ``` What if we wanted to see if the average mass differed by eye color? We'll only look at the 6 most popular eye colors and remove `NA`s. ```{r fct-lump-mean} avg_mass_eye_color <- starwars %>% mutate(eye_color = fct_lump(eye_color, n = 6)) %>% group_by(eye_color) %>% summarise(mean_mass = mean(mass, na.rm = TRUE)) avg_mass_eye_color ``` ## Ordering by another variable It looks like people (or at least one person) with orange eyes are definitely heavier! If we wanted to make a graph, it would be nice if it was ordered by `mean_mass`. We can do this with `fct_reorder()`, which reorders one variable by another. ```{r fct-reorder} avg_mass_eye_color %>% mutate(eye_color = fct_reorder(eye_color, mean_mass)) %>% ggplot(aes(x = eye_color, y = mean_mass)) + geom_col() ``` ## Manually reordering Let's switch to using another dataset, `gss_cat`, the general social survey. What is the income distribution among the respondents? ```{r} gss_cat %>% count(rincome) ``` Notice that the income levels are in the correct order - they start with the non-answers and then go from highest to lowest. This is the same order you'd see if you plotted it as a bar chart. This is not a coincidence. When you're working with ordinal data, where there is an order, you can have an ordered factor. You can examine them with the base function `levels()`, which prints them in order: ```{r} levels(gss_cat$rincome) ``` But what if your factor came in the wrong order? Let's simulate that by reordering the levels of `rincome` randomly with `fct_shuffle()`: ```{r} reshuffled_income <- gss_cat$rincome %>% fct_shuffle() levels(reshuffled_income) ``` Now if we plotted it, it would show in this order, which is all over the place! How can we fix this and put it in the right order? We can use the function `fct_relevel()` when we need to manually reorder our factor levels. In addition to the factor, you give it a character vector of level names, and specify where you want to move them. It defaults to moving them to the front, but you can move them after another level with the argument `after`. If you want to move it to the end, you set `after` equal to `Inf`. For example, let's say we wanted to move `Lt $1000` and `$1000 to 2999` to the front. We would write: ```{r} fct_relevel(reshuffled_income, c("Lt $1000", "$1000 to 2999")) %>% levels() ``` What if we want to move them to the second and third place? ```{r} fct_relevel(reshuffled_income, c("Lt $1000", "$1000 to 2999"), after = 1) %>% levels() ``` forcats/inst/doc/forcats.html0000644000176200001440000027616214004327012015773 0ustar liggesusers Introduction to forcats

Introduction to forcats

Emily Robinson

The goal of the forcats package is to provide a suite of useful tools that solve common problems with factors. Factors are useful when you have categorical data, variables that have a fixed and known set of values, and when you want to display character vectors in non-alphabetical order. If you want to learn more, the best place to start is the chapter on factors in R for Data Science.

Ordering by frequency

library(dplyr)
library(ggplot2)
library(forcats)

Let’s try answering the question, “what are the most common hair colors of star wars characters?” Let’s start off by making a bar plot:

ggplot(starwars, aes(x = hair_color)) + 
  geom_bar() + 
  coord_flip()

That’s okay, but it would be more helpful the graph was ordered by count. This is a case of an unordered categorical variable where we want it ordered by its frequency. To do so, we can use the function fct_infreq():

ggplot(starwars, aes(x = fct_infreq(hair_color))) + 
  geom_bar() + 
  coord_flip()

Note that fct_infreq() it automatically puts NA at the top, even though that doesn’t have the smallest number of entries.

Combining levels

Let’s take a look at skin color now:

starwars %>%
  count(skin_color, sort = TRUE)
#> # A tibble: 31 x 2
#>    skin_color     n
#>    <chr>      <int>
#>  1 fair          17
#>  2 light         11
#>  3 dark           6
#>  4 green          6
#>  5 grey           6
#>  6 pale           5
#>  7 brown          4
#>  8 blue           2
#>  9 blue, grey     2
#> 10 orange         2
#> # … with 21 more rows

We see that there’s 31 different skin colors - if we want to make a plot this would be way too many to display! Let’s reduce it to only be the top 5. We can use fct_lump() to “lump” all the infrequent colors into one factor, “other.” The argument n is the number of levels we want to keep.

starwars %>%
  mutate(skin_color = fct_lump(skin_color, n = 5)) %>%
  count(skin_color, sort = TRUE)
#> # A tibble: 6 x 2
#>   skin_color     n
#>   <fct>      <int>
#> 1 Other         41
#> 2 fair          17
#> 3 light         11
#> 4 dark           6
#> 5 green          6
#> 6 grey           6

We could also have used prop instead, which keeps all the levels that appear at least prop of the time. For example, let’s keep skin colors that at least 10% of the characters have:

starwars %>%
  mutate(skin_color = fct_lump(skin_color, prop = .1)) %>%
  count(skin_color, sort = TRUE)
#> # A tibble: 3 x 2
#>   skin_color     n
#>   <fct>      <int>
#> 1 Other         59
#> 2 fair          17
#> 3 light         11

Only light and fair remain; everything else is other.

If you wanted to call it something than “other”, you can change it with the argument other_level:

starwars %>%
  mutate(skin_color = fct_lump(skin_color, prop = .1, other_level = "extra")) %>%
  count(skin_color, sort = TRUE)
#> # A tibble: 3 x 2
#>   skin_color     n
#>   <fct>      <int>
#> 1 extra         59
#> 2 fair          17
#> 3 light         11

What if we wanted to see if the average mass differed by eye color? We’ll only look at the 6 most popular eye colors and remove NAs.

avg_mass_eye_color <- starwars %>%
  mutate(eye_color = fct_lump(eye_color, n = 6)) %>%
  group_by(eye_color) %>%
  summarise(mean_mass = mean(mass, na.rm = TRUE))

avg_mass_eye_color
#> # A tibble: 7 x 2
#>   eye_color mean_mass
#> * <fct>         <dbl>
#> 1 black          76.3
#> 2 blue           86.5
#> 3 brown          66.1
#> 4 orange        282. 
#> 5 red            81.4
#> 6 yellow         81.1
#> 7 Other          68.4

Ordering by another variable

It looks like people (or at least one person) with orange eyes are definitely heavier! If we wanted to make a graph, it would be nice if it was ordered by mean_mass. We can do this with fct_reorder(), which reorders one variable by another.

avg_mass_eye_color %>%
  mutate(eye_color = fct_reorder(eye_color, mean_mass)) %>%
  ggplot(aes(x = eye_color, y = mean_mass)) + 
  geom_col()

Manually reordering

Let’s switch to using another dataset, gss_cat, the general social survey. What is the income distribution among the respondents?

gss_cat %>%
  count(rincome)
#> # A tibble: 16 x 2
#>    rincome            n
#>  * <fct>          <int>
#>  1 No answer        183
#>  2 Don't know       267
#>  3 Refused          975
#>  4 $25000 or more  7363
#>  5 $20000 - 24999  1283
#>  6 $15000 - 19999  1048
#>  7 $10000 - 14999  1168
#>  8 $8000 to 9999    340
#>  9 $7000 to 7999    188
#> 10 $6000 to 6999    215
#> 11 $5000 to 5999    227
#> 12 $4000 to 4999    226
#> 13 $3000 to 3999    276
#> 14 $1000 to 2999    395
#> 15 Lt $1000         286
#> 16 Not applicable  7043

Notice that the income levels are in the correct order - they start with the non-answers and then go from highest to lowest. This is the same order you’d see if you plotted it as a bar chart. This is not a coincidence. When you’re working with ordinal data, where there is an order, you can have an ordered factor. You can examine them with the base function levels(), which prints them in order:

levels(gss_cat$rincome)
#>  [1] "No answer"      "Don't know"     "Refused"        "$25000 or more"
#>  [5] "$20000 - 24999" "$15000 - 19999" "$10000 - 14999" "$8000 to 9999" 
#>  [9] "$7000 to 7999"  "$6000 to 6999"  "$5000 to 5999"  "$4000 to 4999" 
#> [13] "$3000 to 3999"  "$1000 to 2999"  "Lt $1000"       "Not applicable"

But what if your factor came in the wrong order? Let’s simulate that by reordering the levels of rincome randomly with fct_shuffle():

reshuffled_income <- gss_cat$rincome %>%
  fct_shuffle()

levels(reshuffled_income)
#>  [1] "$8000 to 9999"  "Refused"        "$4000 to 4999"  "$6000 to 6999" 
#>  [5] "$5000 to 5999"  "$10000 - 14999" "$1000 to 2999"  "Lt $1000"      
#>  [9] "Don't know"     "No answer"      "$7000 to 7999"  "Not applicable"
#> [13] "$3000 to 3999"  "$25000 or more" "$20000 - 24999" "$15000 - 19999"

Now if we plotted it, it would show in this order, which is all over the place! How can we fix this and put it in the right order?

We can use the function fct_relevel() when we need to manually reorder our factor levels. In addition to the factor, you give it a character vector of level names, and specify where you want to move them. It defaults to moving them to the front, but you can move them after another level with the argument after. If you want to move it to the end, you set after equal to Inf.

For example, let’s say we wanted to move Lt $1000 and $1000 to 2999 to the front. We would write:

fct_relevel(reshuffled_income, c("Lt $1000", "$1000 to 2999")) %>%
  levels()
#>  [1] "Lt $1000"       "$1000 to 2999"  "$8000 to 9999"  "Refused"       
#>  [5] "$4000 to 4999"  "$6000 to 6999"  "$5000 to 5999"  "$10000 - 14999"
#>  [9] "Don't know"     "No answer"      "$7000 to 7999"  "Not applicable"
#> [13] "$3000 to 3999"  "$25000 or more" "$20000 - 24999" "$15000 - 19999"

What if we want to move them to the second and third place?

fct_relevel(reshuffled_income, c("Lt $1000", "$1000 to 2999"), after = 1) %>%
  levels()
#>  [1] "$8000 to 9999"  "Lt $1000"       "$1000 to 2999"  "Refused"       
#>  [5] "$4000 to 4999"  "$6000 to 6999"  "$5000 to 5999"  "$10000 - 14999"
#>  [9] "Don't know"     "No answer"      "$7000 to 7999"  "Not applicable"
#> [13] "$3000 to 3999"  "$25000 or more" "$20000 - 24999" "$15000 - 19999"