Tukey-Test Группировка и построение графиков в SciPy

Я пытаюсь построить результаты теста Тьюки, но мне трудно разбить данные на группы на основе P-значения. Это эквивалент в R, который я пытаюсь воспроизвести. Я использовал односторонние тесты ANOVA SciPy и тестовую статистическую модель Tukey, но не могу выполнить эти группы одинаково.

Любая помощь приветствуется

Я также только что нашел этот еще один пример в R того, что я хочу сделать в python


person Community    schedule 15.05.2017    source источник
comment
Есть ли общее правило, как назначать смешанное членство, например a,b во второй ссылке? (Я пытался сделать некоторую группировку в песочнице statsmodels давным-давно, но потом сдался, потому что нет группировки, которая разделяет группы. A незначительно отличается от B, B незначительно отличается от C. Но A и C существенно различаются, так что транзитивность отсутствует.)   -  person Josef    schedule 15.05.2017
comment
В пакете R есть ссылка на присвоение букв: Piepho, Hans-Peter (2004) Алгоритм буквенного представления всех попарных сравнений.   -  person Josef    schedule 16.05.2017
comment
BrianM вдохновил меня на создание моей собственной версии с использованием той же бумаги, что и источник метода. Мой метод также можно использовать с scikit_posthocs, и он включает в себя шаг оптимизации методом Монте-Карло для удаления дополнительных ненужных букв; описывается в газете как «зачистка». ‹a› github.com/PhilPlantMan/   -  person Philip Kirk    schedule 09.02.2020
comment
Это в Python ссылка   -  person Nancy    schedule 17.02.2021


Ответы (1)


Я изо всех сил пытался сделать то же самое. Я нашел документ, в котором рассказывается, как кодировать буквы.
Ханс-Питер Пьефо (2004) Алгоритм буквенного представления всепарных сравнений, Журнал вычислительной и графической статистики, 13:2, 456- 466, DOI: 10.1198/1061860043515

Выполнение кодирования было немного сложным, так как вам нужно проверить и реплицировать столбцы, а затем объединить столбцы. Я попытался добавить некоторые комментарии к холоду. Я нашел метод, при котором вы можете запустить tukeyhsd, а затем по результатам вычислить буквы. Должна быть возможность превратить это в функцию. Или, надеюсь, часть tukeyhsd. Мои данные не публикуются, но это столбец данных, а затем столбец, описывающий группы. Группы для меня — это пять районов Нью-Йорка. Вы также можете просто изменить комментарии и использовать случайные данные в первый раз.

# Read data.  Comment out the next ones to use random data.  
df=pd.read_excel('anova_test.xlsx')
#n=1000
#df = pd.DataFrame(columns=['Groups','Data'],index=np.arange(n))
#df['Groups']=np.random.randint(1, 4,size=n)
#df['Data']=df['Groups']*np.random.random_sample(size=n)


# define columns for data and then grouping
col_to_group='Groups'
col_for_data='Data'

#Now take teh data and regroup for anova
samples = [cols[1] for cols in df.groupby(col_to_group)[col_for_data]]    #I am not sure how this works but it makes an numpy array for each group 
f_val, p_val = stats.f_oneway(*samples)  # I am not sure what this star does but this passes all the numpy arrays correctly
#print('F value: {:.3f}, p value: {:.3f}\n'.format(f_val, p_val))

# this if statement can be uncommmented if you don't won't to go furhter with out p<0.05
#if p_val<0.05:    #If the p value is less than 0.05 it then does the tukey
mod = MultiComparison(df[col_for_data], df[col_to_group])
thsd=mod.tukeyhsd()
#print(mod.tukeyhsd())

#this is a function to do Piepho method.  AN Alogrithm for a letter based representation of al-pairwise comparisons.  
tot=len(thsd.groupsunique)
#make an empty dataframe that is a square matrix of size of the groups. #set first column to 1
df_ltr=pd.DataFrame(np.nan, index=np.arange(tot),columns=np.arange(tot))
df_ltr.iloc[:,0]=1
count=0
df_nms = pd.DataFrame('', index=np.arange(tot), columns=['names'])  # I make a dummy dataframe to put axis labels into.  sd stands for signifcant difference

for i in np.arange(tot):   #I loop through and make all pairwise comparisons. 
    for j in np.arange(i+1,tot):
        #print('i=',i,'j=',j,thsd.reject[count])
        if thsd.reject[count]==True:
            for cn in np.arange(tot):
                if df_ltr.iloc[i,cn]==1 and df_ltr.iloc[j,cn]==1: #If the column contains both i and j shift and duplicat
                    df_ltr=pd.concat([df_ltr.iloc[:,:cn+1],df_ltr.iloc[:,cn+1:].T.shift().T],axis=1)
                    df_ltr.iloc[:,cn+1]=df_ltr.iloc[:,cn]
                    df_ltr.iloc[i,cn]=0
                    df_ltr.iloc[j,cn+1]=0
                #Now we need to check all columns for abosortpion.
                for cleft in np.arange(len(df_ltr.columns)-1):
                    for cright in np.arange(cleft+1,len(df_ltr.columns)):
                        if (df_ltr.iloc[:,cleft].isna()).all()==False and (df_ltr.iloc[:,cright].isna()).all()==False: 
                            if (df_ltr.iloc[:,cleft]>=df_ltr.iloc[:,cright]).all()==True:  
                                df_ltr.iloc[:,cright]=0
                                df_ltr=pd.concat([df_ltr.iloc[:,:cright],df_ltr.iloc[:,cright:].T.shift(-1).T],axis=1)
                            if (df_ltr.iloc[:,cleft]<=df_ltr.iloc[:,cright]).all()==True:
                                df_ltr.iloc[:,cleft]=0
                                df_ltr=pd.concat([df_ltr.iloc[:,:cleft],df_ltr.iloc[:,cleft:].T.shift(-1).T],axis=1)

        count+=1

#I sort so that the first column becomes A        
df_ltr=df_ltr.sort_values(by=list(df_ltr.columns),axis=1,ascending=False)

# I assign letters to each column
for cn in np.arange(len(df_ltr.columns)):
    df_ltr.iloc[:,cn]=df_ltr.iloc[:,cn].replace(1,chr(97+cn)) 
    df_ltr.iloc[:,cn]=df_ltr.iloc[:,cn].replace(0,'')
    df_ltr.iloc[:,cn]=df_ltr.iloc[:,cn].replace(np.nan,'') 

#I put all the letters into one string
df_ltr=df_ltr.astype(str)
df_ltr.sum(axis=1)
#print(df_ltr)
#print('\n')
#print(df_ltr.sum(axis=1))

#Now to plot like R with a violing plot
fig,ax=plt.subplots()
df.boxplot(column=col_for_data, by=col_to_group,ax=ax,fontsize=16,showmeans=True
                    ,boxprops=dict(linewidth=2.0),whiskerprops=dict(linewidth=2.0))  #This makes the boxplot

ax.set_ylim([-10,20])

grps=pd.unique(df[col_to_group].values)   #Finds the group names
grps.sort() # This is critical!  Puts the groups in alphabeical order to make it match the plotting

props=dict(facecolor='white',alpha=1)
for i,grp in enumerate(grps):   #I loop through the groups to make the scatters and figure out the axis labels. 

    x = np.random.normal(i+1, 0.15, size=len(df[df[col_to_group]==grp][col_for_data]))
    ax.scatter(x,df[df[col_to_group]==grp][col_for_data],alpha=0.5,s=2)
    name="{}\navg={:0.2f}\n(n={})".format(grp
                            ,df[df[col_to_group]==grp][col_for_data].mean()
                            ,df[df[col_to_group]==grp][col_for_data].count())
    df_nms['names'][i]=name 
    ax.text(i+1,ax.get_ylim()[1]*1.1,df_ltr.sum(axis=1)[i],fontsize=10,verticalalignment='top',horizontalalignment='center',bbox=props)


ax.set_xticklabels(df_nms['names'],rotation=0,fontsize=10)
ax.set_title('')
fig.suptitle('')

fig.savefig('anovatest.jpg',dpi=600,bbox_inches='tight')

Результаты, показывающие буквы выше на графиках с использованием tukeyhsd

person BrianM    schedule 31.08.2019