From 84729389ddfbbfb46a40c4e3d0c5c8c4e75679ca Mon Sep 17 00:00:00 2001 From: timyerg Date: Sat, 7 Dec 2024 20:54:05 +0100 Subject: [PATCH] Now cld4py can add letters to seaborn/matplotlib figures --- cld4py/__init__.py | 2 + cld4py/__pycache__/__init__.cpython-310.pyc | Bin 0 -> 236 bytes cld4py/__pycache__/__init__.cpython-38.pyc | Bin 0 -> 226 bytes cld4py/__pycache__/__init__.cpython-39.pyc | Bin 0 -> 226 bytes .../assign_letters.cpython-310.pyc | Bin 0 -> 2824 bytes .../__pycache__/assign_letters.cpython-38.pyc | Bin 0 -> 2739 bytes cld4py/__pycache__/cld4py.cpython-310.pyc | Bin 0 -> 2766 bytes cld4py/__pycache__/cld4py.cpython-38.pyc | Bin 0 -> 6441 bytes cld4py/__pycache__/cld4py.cpython-39.pyc | Bin 0 -> 6421 bytes .../__pycache__/cld4py_main.cpython-310.pyc | Bin 0 -> 2797 bytes cld4py/cld4py.py | 168 ++++++++++++++++++ pyproject.toml | 4 +- src/cld4py.egg-info/PKG-INFO | 54 ------ src/cld4py.egg-info/SOURCES.txt | 8 - src/cld4py.egg-info/dependency_links.txt | 1 - src/cld4py.egg-info/top_level.txt | 1 - src/cld4py/__init__.py | 0 src/cld4py/cld4py.py | 54 ------ 18 files changed, 172 insertions(+), 120 deletions(-) create mode 100644 cld4py/__init__.py create mode 100644 cld4py/__pycache__/__init__.cpython-310.pyc create mode 100644 cld4py/__pycache__/__init__.cpython-38.pyc create mode 100644 cld4py/__pycache__/__init__.cpython-39.pyc create mode 100644 cld4py/__pycache__/assign_letters.cpython-310.pyc create mode 100644 cld4py/__pycache__/assign_letters.cpython-38.pyc create mode 100644 cld4py/__pycache__/cld4py.cpython-310.pyc create mode 100644 cld4py/__pycache__/cld4py.cpython-38.pyc create mode 100644 cld4py/__pycache__/cld4py.cpython-39.pyc create mode 100644 cld4py/__pycache__/cld4py_main.cpython-310.pyc create mode 100644 cld4py/cld4py.py delete mode 100644 src/cld4py.egg-info/PKG-INFO delete mode 100644 src/cld4py.egg-info/SOURCES.txt delete mode 100644 src/cld4py.egg-info/dependency_links.txt delete mode 100644 src/cld4py.egg-info/top_level.txt delete mode 100644 src/cld4py/__init__.py delete mode 100644 src/cld4py/cld4py.py diff --git a/cld4py/__init__.py b/cld4py/__init__.py new file mode 100644 index 0000000..3761596 --- /dev/null +++ b/cld4py/__init__.py @@ -0,0 +1,2 @@ +from .cld4py import assign_letters +from .cld4py import plot_letters \ No newline at end of file diff --git a/cld4py/__pycache__/__init__.cpython-310.pyc b/cld4py/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3dd1efbdbcb885e0ed9aa86eb245148880755434 GIT binary patch literal 236 zcmYk0u?oU45QdYsmLgPq1lKNR(M`mmvxB{1p5p=iLaE^$5P}G*Nbz-A1R@Zj3friNC~meSi|%+u)_01` zs2`O8vgx?0ovSTm10RF4vTJ;7%1)Hv10#G~DKRs>4Y713HbMK~IcG=R*39)Rx7r-^ nneFx*Dl3fx_AUL4bJg`k0;h`LbY~#_7{oyaOhAqU5Esh;i4=wu#vF!R#wbQc5St0eW{P40vYCS! zG+ACU0+nbo-r`FvF3wEPi_b|dDM>9V28!?$qb& literal 0 HcmV?d00001 diff --git a/cld4py/__pycache__/__init__.cpython-39.pyc b/cld4py/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9e3ae2803c58210d74fc68d0ae5cbc054eb411c8 GIT binary patch literal 226 zcmYe~<>g`k0;h`LbY~#_7{oyaOhAqU5Esh;i4=wu#vF!R#wbQc5St0eW{P40vYCS! zG+ACU0+nbo-r`FvF3wEPi_b|dDM>9V28!?$q5opsi`&dfL^ zXe}Y7Qk+U$yqCOJj<`bNPw+S9mJ7sR-~u>j*0J4E*4o*bopYXf=A7ruI&ZZa1g>9x z{;VhJg#3zw<;#P?eYo{qXao^7C7tp~JFL#?R8)i~{3o>INnZqqO#Md&r-Xv#LwC2U zzk?^)`|bZf;Pumo5iB#mR-spg8<){fDIoZ>bP69+ZN{+rdtHxB+OWWy77tWRf<90s`#;3q9W<{(2O3^G4VuaEx{%;D%3{bb|AYd9}P8soR|Zi&>a~n@jXy3o6lhrrYH*=(>Ano$qb|LX@YYL8f_790og%&@Jxvv@Z>aAf5R; z)P2Z5s4S7<1vEZE^0yYtl^H1MfMdx>@ck2D6@oy)`~@fvje=eCr2t?+mP5c*sjj6x z>zVGB_OgaT!{E7$>NOr_g0DGFYgjF14rUx3C&>pg%odao0093X*%Gka#A7H9P!#GF z;tH@mX%?znV1bWzSPS(z_-8d+A}_ogyJt1K@G2*h3@UpNq9{wh2#$vNh5Z2TSK!t= z&=jl>H=f1?Ib_g-)3~6A?Ed9j=+EB5{C)BfoaHf`?R_fH(mNz@{;)j-9|U+>FU=$C zC(yS2j+Y+a!Dh=c5!=9NsO?#{dk5|8+k~-Wew}>#?!Pf#nEyMiw*bh|YK|$8BF9ugR;NJlf-cc(Q(J+8 zg_8uR;V0eFV|eFlY4n1jdI@H>E~&jmY_N-mXQ%p!`-W)nsLl>uOP=9`{|-=NPG1~4 zj?)T!Z(P@~xn~eriB@x)?3XXE?!LDt^7>`U_b(OS# zVtuUtP7}?$WhvSq$%OpI)};drjkJ}~5Nc3bFU(G$5yDnxwthcPGKC@O)M2Tvb8W9G z)RMygQmTdx{>xGoXl&rlAnRjITOW@I8#pe2t0Nl-6~@NW1oQ-j1=UdouJ$|_YR<(^ zUB%vivAKqgli%vII>U77b!e{NsCd_C&EvENziad+ZFpDdRp@WhRm#3&e_nUvE!v<8 z|76-)w>t=vtlMn|3X5b9u69Mej&qeEoUfr)D9pKa2I1{?A+F$6rgUC2CAZr4AQz)l X-oyIS$i7Bulrcsdf7R|bsQ=gBJ@e@+ literal 0 HcmV?d00001 diff --git a/cld4py/__pycache__/assign_letters.cpython-38.pyc b/cld4py/__pycache__/assign_letters.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0a01c34c8a5ea1c217c749c3aa4dc0699ca2fad7 GIT binary patch literal 2739 zcmZ`*%WfMt6eZ`Omn}O_r*4au=*AY{H_}B@BMAZ{-UM!tq(GZCaL2#)cFV5H1YK1_1_Vc4vEy82NBY&iXWF&J! zt55p0Z-q9e+F335pg7^*o-ImoWXN9adg$1*1qU>QQD-6q73D9x1az@T*b0#ZhWnOq`HD?jK z=SHMXEYho-7F9KKPv{PL^27I5Z>Be!RfcofOg7t~5j~?6*umPJQ#YF(xGh_}R`UZJ z$0t^u_U*nKTD-_hFG^V@n^`0~z!mw**ZF*SVc;Ul;p@ZS`^Av*axOc(cxGfNFm9H3 zh0oM2KKqjPs$)Jkkk6?zaCmiisqgd)u+toBtLmVLj8A}HXl2#rUyMk3(nbH;dxblEE7p7KJJ&-WWsVarqW;0Pj;X(DU+HmJJ0xx#k0 z0Kre=Zaa}IN+t(Ee8b-yA9iMSbEt{>eZ)Wlx%#`cJF7=t+zr^W$D3WL0=~jTRBxzT zV;*01(A-`;IhhxC8Xf|J-Ey<}0odp$h}kj^La!Suwz0PH`51z+RB&(&sO+T)Y&Mdr zt*|(f3Rc;7OP=(DghxqzX@xEEU_5&=IZ=Kf=pQvA3CL>^sJXO^S5n>x!91{xaAcvLPiFX3#-a9YA_$$c>5 zXgCF|9eBxv5&{6=|3Wqg%n$Jtk^>?N;}z@*u=PMqqH=--I?`ZGqR+s;8M8U^M9Z*y zGiE1R`C^nnX16^I%3RNf(lBl~#`=F59=QWuW;Nl#dYqA#1tX}(8Esj&&)>p$^cL1{ zlRHq&L#Xae%2Cp85vV`b-d_L(|JsgIUpo=>HRrJ%A8lf{r7a$6*ThiG*4FMOJX@OH ze?|WJa=nqZgLQShz9Z7kLHca{(YO237g0yabwB3UJICjLd9?1I$7<(T7bCfk5&R)+ zE-j=$pMUz6*fwwhTi;w8$?gHm@;I4vWs*vwif5qa&xb2++z@$ev;~;d!B|h`dUOD$ z8qgE#XY0^;NCaNHrh_f4wGB<c6YIaJ}%xfH;DwT;;8g$@&+&bO29*zC}S`%ygq=tj`kqdG7D~aX8IK-*q&3?1jXFp_neX_N>wi!Q@f`$n}kCorl6epiVScKF35(BRrN)kr&- z-P*xopU2ZMRe2 Qjf0zJ7xRUBo@4+12QIkOG5`Po literal 0 HcmV?d00001 diff --git a/cld4py/__pycache__/cld4py.cpython-310.pyc b/cld4py/__pycache__/cld4py.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..38191e65e3612b6123bcf78f3677b208590f24ba GIT binary patch literal 2766 zcmZ`*&2QT_6elUmpK+3Yr6^XkTra7Ce0LkLA!vgkXf8!ow7o1{5h$YM$WbJRq|>I5 zfdMHHr$7%oZYKvj^x#XrH0Z2s}f&v?Cm-~;IJ znuJ~nZUj|tDIpoj3L!foC-j7c03g_#%BiDCi=GxU(qlJBpJ}I6IHNdPB^fNX$K;%L zHO>>5FP#BOkLJDWr@Rt7qhl zwrW`^tBB$|)|x=JDB_Y z)XgS(?w%vx>ZzWC{bSaoC(el*GEoxcH|4CF)oze=;EH_J+kD)g?zxC^5FI=}DTP#2 za@+o;GiytMajPtS zWABKEspM@hk}o3_fK8&Mr?gtIAR996v=x6D>0O?rTt&?!3M1c3G`NRhAcMpY6j!^R z47fKy&RwnlV^4bf0j#FJv187k1P7f+2I73oxd@RipXb8UUWoSjdP6Gw?ifATf{av} zs7AgFx^67b@r@Ng@YA@npC}$Bqm3ZG_;JicpVxV?C^GcRuMdI$`0%fsde5TnB&=66L9dYxGFrG=$0hY*~n zQb20JWiw4+v4K@%j>nPGFw39Mddd$H5hcypIX)|b;poL^NBM@JeYP7ZNbVpB5QjMC zfEfX{-VFw;r6KnerWRt8Yh#f8Aq;jbp?Pliv=e9$K|Jucs5_8fE|#zVkmuCB2?tAXyu_A-k?!{FJBs#)$O zg3nq`vsf*84h9@8r-1JVUNWMD008(u$>xChCSF2ufTB>Z5LbY02708*5f=C;i#1Z8 zg}y^o`8Dz_oaG^$?JX+M(%B<${;*969|U+BCr*7+h@fp0ww(BI8JiWuL}*;A zp@w7F#xmS1hCY5z{=T=ko9+jT`e<=ortO{d)#9`7x0NrWwpNRNEWT(TU3@IGk4!02 z+o;@Iu&83ttkc)Gb1`q9OL-MIK#cD%3~V=nU1eBAraCGiSx4^FK78EA`Gv^CV9mgw z2|;>M>e3#Bs7H_4Pwap_B@(~Fwt*$s!jhqJgUJbaX;{3H&(?5MT}6qbIPNdQ*fO6X zukU<{`N;g!v@isgR;^2c6gi|4ve^fMXLO8SgPI}~Dx4rdZ3@ZILwHwEfmS1i@-oca zJEwMw7S%<2Ah)1O<*$Ub@G6k%AQ$zFZyabIKB_eobDuD&_ zbYO~|Hq>5V94|S7MhH_J*cMu8lt>JTslZa(*0nJyQA-m4L&-8W`0q*g?|IFC&3awK4H8?a}iKVd#SEC?rLe~`AaGH8b j-iCp-$rCrMjGRGvbw3rIIJl2hrf{-M%9J^bPX7BJL~7X- literal 0 HcmV?d00001 diff --git a/cld4py/__pycache__/cld4py.cpython-38.pyc b/cld4py/__pycache__/cld4py.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9bb0a57e7807dda314f9c9a8ddfe0eb6013b589a GIT binary patch literal 6441 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 Q1$43uX8fmg4duuG1-ZJ-H~;_u literal 0 HcmV?d00001 diff --git a/cld4py/__pycache__/cld4py_main.cpython-310.pyc b/cld4py/__pycache__/cld4py_main.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..bb1895e0cab65da43b81b562f64d1bf70bbb5fea GIT binary patch literal 2797 zcmZ`*&u<(x6t+Dx`!kysC@tle%qd+dP12}H2t}nr5xJmHC>Iv0)nx41%w~3GV|!DA zW+kLl%BB(rj&RzD6aSKLhy&tZ-~hbm+3s#j@oGHw*zfb_=kGml-fA@nl;3{&y!TC= zkl(ShTs-L9hezLqN)SO)(kb7x!|JR~MMZeRe?mK+^hI#Q)EhE5BNS#nbWgkbCs>mG zKYsoR%da0ru*|%yLaPc7E~B4PLJCs&F*_&c^qj?>pn^TAUwDS}=|!a=6LynKneqDm zCB@zjDFWfaqU$CwI8I=^dI=~KTDESGGkQkH0nGDHi24HFKyq9!Dn)e(3wk@mc+*-@ znbwOMpyO!cl3db$v#1tzQTc)OR}gy~B&0_e8#gYhrd0%IbeBBZ`i700vZ^sEXQ?TG1$)H_0w=MZWrJ*`HpW z1c-8+9DjXYjj5=YbEmIdy15h>_iLgdnmr~~exT#loX^|H=fa=(qBVW>+&{0tN~>sX zT9Ya=J_CL+D_Z^6ie`xrgExkI#na?l4{KEKG-oAp(QnO1DK4d~_mHeoM$W z9HoYDZEU?ihu}O{0*(eu_VWxDo6Tyk^EA;0M)}ukp^juGlB~D3&ew#T_Z}^FRBj0B zFAoz9hdVn2@I#t%z)S$!9Lm{hdCWtNM+?3wwJ|&WISe)&q1)W;=|CC~K{~T{s0VQV zpt3}Ym(chW$=_ZqSDrvg2MkL_f*+g$s}KYV(_ez}&?wk7UvdCCWZ4B=mFimBv!3a0 zX)kLiG<2RjQN6~)Oz<_wX$_;LJcAiW$4T;m46_9#1OUMQNVWtlH}M#P0~CdN1-}Ap zPnv})7g%7U9o9m94*q$~mdFb$$L@K}F09JIB!kEvgec0=E`roBFW3&?c?}-D3su4T z@L)DB$Pt4UWaEM!vHQ=yLVNZV#_yAlA(zLH+xt}DOz((5{$cwHE(Ca6FU=$CCs4Qj zj+dU?!D`zw5!=9NsO?#{cL$zrOCS77{`z3^FdxWGbGo^!^5H@L?dF$Xb#;@nf$q0<8oJ*tlB1pG6hXY5CI%pMYjm$Iv13AV9iY1(FL1wLAqZkMA? z>@{{!->8gxThMomuaocIe39{D+W*se7XTcc=9mH*azYgx;S`8n(j{7LYAX<(kT!r4 z-rtsUbFbOccZGASKbdl3w^=KQCwV(U$; zu3_b5S1I*{$E4Sxx_-0bU86OR(;ED)(Ob0PU8Pr{y+v0k`=0%M-SxL=gDU(dX=_~< za@}q_P#6^ZP}&vs7LHYhkVHeRP>}Q48Mw9E1%E=ImPa{{k&;twXON3gD(_*uX=Gg^ QHOd&Hjelx)8`S^jUt|#6#{d8T literal 0 HcmV?d00001 diff --git a/cld4py/cld4py.py b/cld4py/cld4py.py new file mode 100644 index 0000000..a0d746f --- /dev/null +++ b/cld4py/cld4py.py @@ -0,0 +1,168 @@ +import string +import pandas as pd + + +def assign_letters(df, G1, G2, P, alpha=.05, + order=None, data=None, vals=None, group=None): + """ + Function to apply compact letter display for pairwise contrasts. + Groups with no significant differences share a letter. + + Parameters: + + Required: + df - dataframe with contrasts (pairwise comparisons). + G1, G2 - columns in contrasts df with compared groups. + P - column in contrasts df with p-value (adjusted, right?). + + Optional: + alpha - sigificance level (default 0.05). + order - None (default), list or ['ascending', 'descending']. + This parameter will define the order of assigned letters. + None - alphabetical order will be applied. + List - order of groups will be defined by that list. + String 'ascending' or 'descending' requires parameters + 'data', 'values' and 'group' to order groups by the mean. + data - dataframe with values that were compared to get contrasts. + vals - column in data with compared values. + group - column in data with group information. + """ + + #helper function to check p + def is_sign(lv1, lv2, df=df, alpha=alpha): + return df.loc[(df[G1]==lv1)&(df[G2]==lv2)|(df[G1]==lv2)&(df[G2]==lv1),P].iloc[0] < alpha + + letters = string.ascii_lowercase + df[P] = df[P].apply(pd.to_numeric) + + #define order + if order == None: + order = sorted(set(df[G1].tolist() + df[G2].tolist())) + if order in ['ascending', 'descending']: + asc = order=='ascending' + data[vals] = data[vals].apply(pd.to_numeric) + order = pd.DataFrame(data.groupby(group)[vals].mean()).sort_values(vals, ascending=asc).index.tolist() + + #assign letters + draft, sets = {}, [] + for i, l1 in enumerate(order): + draft.update({i: {l1}}) + for l2 in order: + if l1 != l2 and not any([is_sign(l1,l2)]+[is_sign(l,l2) for l in draft[i]]): + draft[i].add(l2) + [sets.append(v) for v in draft.values() if v not in sets] + cld = pd.DataFrame(columns=['Group', 'Letters']) + for i,l in enumerate(order): + cld.loc[i, ['Group', 'Letters']] = l, ''.join([letters[j] for j,s in enumerate(sets) if l in s]) + return cld.set_index('Group') + + +def plot_letters(cld, data, vals, group, figax, + axis='x', plot='boxplot', pos='upper', + pad=1, c='black', fs=None, lim=0): + """ + Function to plot CLD letters for sns boxplot, violinplot, barplot or swarmplot. + Groups with no significant differences share a letter. + + Parameters: + + Required: + cld - dataframe or dictionary with groups and letters. If df then groups + should be in the index and letters in the "Letters" column. + data - dataframe with values that were plotted. + vals - column in data with compared values. + group - column in data with group information. + figax - matplotlib or sns figure or ax with plot. + + Optional: + axis - axis with plotted groups: "x" or "y" (default "x"). + plot - plot type: "boxplot", "violinplot", "barplot" or "swarmplot" + (default "boxplot"). + pos - letters position: "upper", "lower", "top" or "bottom" + (default: "upper"). If axis = "y", "upper" and "top" will be + plotted on the right side, "lower" and "bottom" - on the left. + pad - distance (% of data range) to the plotted group object (default 1). + c - color of letters. + fs - fontsize of letters. + lim - increase axes limits, expressed in "pad" (see above) values (default 0) + """ + + #import + import seaborn as sns + import matplotlib.pyplot as plt + from matplotlib.cbook import boxplot_stats + + types = ['boxplot', 'violinplot', 'barplot', 'swarmplot'] + labels = figax.get_xticklabels() if axis=="x" else figax.get_yticklabels() + step = (data[vals].max() - data[vals].min())/100 * pad + + #check parameters + if axis not in "xy": + raise ValueError('axis should by either "x" or "y"') + if plot not in types: + raise ValueError(f'"{plot}" is not in the list of supported types') + if pos not in ["upper", "lower", "top", "bottom"]: + raise ValueError('pos should by either "upper", "lower", "top" or "bottom"') + if not any([isinstance(cld, pd.DataFrame), isinstance(cld, dict)]): + raise ValueError('cld should by either dataframe or dictionary') + if fs == None: + fs = labels[0].get_fontsize() + + #set limits + if axis=="y": + va = 'center' + lims = figax.get_xlim() + figax.set_xlim(min(lims)-lim*step, max(lims)+lim*step) + if axis=="x": + lims = figax.get_ylim() + figax.set_ylim(min(lims)-lim*step, max(lims)+lim*step) + + #plot letters + pos_dict = { + 'top': max(figax.get_ylim())-step if axis=='x' else max(figax.get_xlim())-step, + 'bottom': min(figax.get_ylim())+step if axis=='x' else min(figax.get_xlim())+step} + + if axis=='x': + ha = 'center' + va = 'bottom' if pos in ['upper', 'bottom'] else 'top' + if axis=='y': + va = 'center' + ha = 'left' if pos in ['upper', 'bottom'] else 'right' + if not isinstance(cld, dict): + cld = {i: cld.loc[i, 'Letters'] for i in cld.index} + + + for i, label in enumerate(labels): + df = data.loc[data[group]==label.get_text()] + rel_step = (df[vals].max() - df[vals].min())/1.7 + x, y = label.get_position() + + #boxplot + if plot == 'boxplot': + pos_dict.update({'upper': boxplot_stats(df[vals])[0]['whishi'] + step}) + pos_dict.update({'lower': boxplot_stats(df[vals])[0]['whislo'] - step}) + + #violinplot + if plot == 'violinplot': + pos_dict.update({'upper': df[vals].max() + rel_step + step}) + pos_dict.update({'lower': df[vals].min() - rel_step - step}) + + #barplot + if plot == 'barplot': + line = figax.lines[i] + gain = line.get_ydata() if axis=="x" else line.get_xdata() + pos_dict.update({'upper': step + abs(max(gain))}) + pos_dict.update({'lower': -step + abs(min(gain))}) + + #swarmplot + if plot == 'swarmplot': + pos_dict.update({'upper': df[vals].max() + step}) + pos_dict.update({'lower': df[vals].min() - step}) + + xpos = x if axis=="x" else pos_dict[pos] + ypos = y if axis=="y" else pos_dict[pos] + if plot == 'barplot': + mn, mx = 0, max(lims)+lim*step + [figax.set_ylim(mn, mx) if axis=='x' else figax.set_xlim(mn, mx)] + + figax.text(xpos, ypos, cld[label.get_text()], size=fs, color=c, ha=ha, va=va,) \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index 8c4e762..935a3ab 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,11 +4,11 @@ build-backend = "setuptools.build_meta" [project] name = "cld4py" -version = "1.0.1" +version = "1.1.0" authors = [ { name="Timur Yergaliyev", email="timyerg@gmail.com" }, ] -description = "Python 3 function to assign compact letter display letters" +description = "Python 3 function to assign compact letter display letters and for plotting them with matplotlib/seaborn" readme = "README.md" requires-python = ">=3.7" classifiers = [ diff --git a/src/cld4py.egg-info/PKG-INFO b/src/cld4py.egg-info/PKG-INFO deleted file mode 100644 index 9f51996..0000000 --- a/src/cld4py.egg-info/PKG-INFO +++ /dev/null @@ -1,54 +0,0 @@ -Metadata-Version: 2.1 -Name: cld4py -Version: 1.0.1 -Summary: Python 3 function to assign compact letter display letters -Author-email: Timur Yergaliyev -Project-URL: Homepage, https://github.com/timyerg/cld4py -Project-URL: Bug Tracker, https://github.com/timyerg/cld4py/issues -Classifier: Programming Language :: Python :: 3 -Classifier: License :: OSI Approved :: Apache Software License -Classifier: Operating System :: OS Independent -Requires-Python: >=3.7 -Description-Content-Type: text/markdown - -# Python 3 function to assign compact letter display letters - -Function to apply compact letter display for pairwise contrasts. -Groups with no significant differences share a letter. - -## Parameters: - - -```python -Required: - df - dataframe with contrasts (pairwise comparisons). - G1, G2 - columns in contrasts df with compared groups. - P - column in contrasts df with p-value (adjusted, right?). -Optional: - alpha - sigificance level (default 0.05). - order - None (default), list or ['ascending', 'descending']. - This parameter will define the order of assigned letters. - None - alphabetical order will be applied. - List - order of groups will be defined by that list. - String 'ascending' or 'descending' requires parameters - 'data', 'values' and 'group' to order groups by the mean. - data - dataframe with values that were compared to get contrasts. - vals - column in data with compared values. - group - column in data with group information. -``` - -## Installation - - -```python -pip install cld4py -``` - -## Usage - - -```python -from cld4py.cld4py import * - -cld4py(*args) -``` diff --git a/src/cld4py.egg-info/SOURCES.txt b/src/cld4py.egg-info/SOURCES.txt deleted file mode 100644 index bccef14..0000000 --- a/src/cld4py.egg-info/SOURCES.txt +++ /dev/null @@ -1,8 +0,0 @@ -README.md -pyproject.toml -src/cld4py/__init__.py -src/cld4py/cld4py.py -src/cld4py.egg-info/PKG-INFO -src/cld4py.egg-info/SOURCES.txt -src/cld4py.egg-info/dependency_links.txt -src/cld4py.egg-info/top_level.txt \ No newline at end of file diff --git a/src/cld4py.egg-info/dependency_links.txt b/src/cld4py.egg-info/dependency_links.txt deleted file mode 100644 index 8b13789..0000000 --- a/src/cld4py.egg-info/dependency_links.txt +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/cld4py.egg-info/top_level.txt b/src/cld4py.egg-info/top_level.txt deleted file mode 100644 index ae4f7e9..0000000 --- a/src/cld4py.egg-info/top_level.txt +++ /dev/null @@ -1 +0,0 @@ -cld4py diff --git a/src/cld4py/__init__.py b/src/cld4py/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/src/cld4py/cld4py.py b/src/cld4py/cld4py.py deleted file mode 100644 index c887dec..0000000 --- a/src/cld4py/cld4py.py +++ /dev/null @@ -1,54 +0,0 @@ -import string -import pandas as pd - -def cld4py(df, G1, G2, P, alpha=.05, - order=None, data=None, vals=None, group=None): - """ - Function to apply compact letter display for pairwise contrasts. - Groups with no significant differences share a letter. - - Parameters: - Required: - df - dataframe with contrasts (pairwise comparisons). - G1, G2 - columns in contrasts df with compared groups. - P - column in contrasts df with p-value (adjusted, right?). - Optional: - alpha - sigificance level (default 0.05). - order - None (default), list or ['ascending', 'descending']. - This parameter will define the order of assigned letters. - None - alphabetical order will be applied. - List - order of groups will be defined by that list. - String 'ascending' or 'descending' requires parameters - 'data', 'values' and 'group' to order groups by the mean. - data - dataframe with values that were compared to get contrasts. - vals - column in data with compared values. - group - column in data with group information. - """ - - #helper function to check p - def is_sign(lv1, lv2, df=df, alpha=alpha): - return df.loc[(df[G1]==lv1)&(df[G2]==lv2)|(df[G1]==lv2)&(df[G2]==lv1),P].iloc[0] < alpha - - letters = string.ascii_lowercase - df[P] = df[P].apply(pd.to_numeric) - - #define order - if order == None: - order = sorted(set(df[G1].tolist() + df[G2].tolist())) - if order in ['ascending', 'descending']: - asc = order=='ascending' - data[vals] = data[vals].apply(pd.to_numeric) - order = pd.DataFrame(data.groupby(group)[vals].mean()).sort_values(vals, ascending=asc).index.tolist() - - #assign letters - draft, sets = {}, [] - for i, l1 in enumerate(order): - draft.update({i: {l1}}) - for l2 in order: - if l1 != l2 and not any([is_sign(l1,l2)]+[is_sign(l,l2) for l in draft[i]]): - draft[i].add(l2) - [sets.append(v) for v in draft.values() if v not in sets] - cld = pd.DataFrame(columns=['Group', 'Letters']) - for i,l in enumerate(order): - cld.loc[i, ['Group', 'Letters']] = l, ''.join([letters[j] for j,s in enumerate(sets) if l in s]) - return cld.set_index('Group') \ No newline at end of file