knitr::opts_chunk$set(
    echo = TRUE,
    message = FALSE,
    warning = FALSE
)
knitr::opts_knit$set(root.dir = normalizePath(".."))

Introdução

Esse é um notebook do R, escrito em R Markdown. Quando tu executas o código no notebook, os resultados aparecem embaixo do código. Eu acho uma forma legal de garantir a reprodutibilidade das análises e de mesclar comentário com resultados das análises.

Sobre os dados

Eu estou usando, com o consentimento da minha aluna, uma base de dados proveniente de um TCC que eu orientei sobre marcas humanizadas. Ela coletou 326 casos via Qualtrics, em um design de 2 fatores entre participantes: Marca “Controle” e Marca “Humanizada”.

A condição de controle apresenta o tweet stream de uma marca fictícia de celulares, lidando com um problema de uma cliente. Controle

A condição experimental apresenta a mesma marca fictícia em um tom conversacional descontraído, com gifs, imagens e informalidade. Experimental

Existem problemas de design e confounds (e.g., reclamação só na condição controle, múltiplas dimensões da humanização manipuladas de uma só vez, etc.), mas para efeitos de análise ignoraremos essas limitações por ora.

O primeiro passo é importar os dados. Eu recomendo usar sempre os dados “mais brutos”, ou seja, sem qualquer forma de processamento. No Qualtrics, essas opções são texto (TXT) ou texto - valores separados por vírgula (CSV). Ao exportar, podemos escolher se queremos os dados como variáveis nominais (“choice text”) ou números. Eu recomendo baixar os dois e usa-los de acordo com a necessidade. Não esquecer de pedir para o Qualtrics exportar a ordem da randomização das variáveis. Isso adiciona muitas variáveis à base de dados, mas é informação que pode ser útil. Outro desafio diz respeito ao formato de exportação. O Qualtrics, por default, exporta três “cabeçalhos” na base de dados, contendo nome da variável, descrições e enunciados. Se nós importarmos os dados diretos, o R julgará que todas as variáveis são strings e as operações com os dados serão limitadas (além, claro, de estarem erradas). Por isso, eu importo os dados apenas e, depois, adiciono os nomes das variáveis às bases de dados. Eu poderia abrir os dados no Excel e apagar duas linhas, mas eu quero evitar “tocar” na base de dados para minimizar chances de erro.

#importando dados numéricos como dn
require(readr)
setwd("/home/lnicolao/Google Drive/Drive/UFRGS/Ensino/20211/ADP - Experimentos/Scripts Aulas/TCC_Karen/")
dn<-read_csv("TCC_Karen_Numeros.csv",
             col_names = FALSE, skip = 3)
names(dn)<-read_csv("TCC_Karen_Numeros.csv",
                    col_names = FALSE)[1,]

#importando dados em texto como dt
dt<-read_csv("TCC_Karen_Strings.csv",
             col_names = FALSE, skip = 3)
names(dt)<-read_csv("TCC_Karen_Strings.csv",
                    col_names = FALSE)[1,]

Uma inspeção inicial mostra que a base “em texto” já considera as escalas como números. Podemos usar apenas essa para a análise. A função “head” mostra as primeiras cinco linhas da base / objeto. Aliás, essa função é comum a muitas linguagens de programação, inclusive ao Python.

head(dn)
head(dt)

Porque minha aluna já tinha me dito que ela testou duas vezes o questionário, eu sei que precisamos nos livrar das primeiras duas linhas de dados. Mas vamos confirmar se esse é o caso.

names(dt)
##  [1] "StartDate"             "EndDate"               "Status"               
##  [4] "IPAddress"             "Progress"              "Duration (in seconds)"
##  [7] "Finished"              "RecordedDate"          "ResponseId"           
## [10] "RecipientLastName"     "RecipientFirstName"    "RecipientEmail"       
## [13] "ExternalReference"     "LocationLatitude"      "LocationLongitude"    
## [16] "DistributionChannel"   "UserLanguage"          "Consentimento"        
## [19] "Q01"                   "Q02"                   "Q03"                  
## [22] "Q04"                   "Q05"                   "Q06"                  
## [25] "Q07"                   "Q08"                   "Q09"                  
## [28] "Q10"                   "Q11"                   "Q01"                  
## [31] "Q02"                   "Q03"                   "Q04"                  
## [34] "Q05"                   "Q06"                   "Q07"                  
## [37] "Q08"                   "Q09"                   "Q01"                  
## [40] "Q01"                   "Q02"                   "Q03"                  
## [43] "Q04_1"                 "Q04_2"                 "Q04_3"                
## [46] "Q05"                   "Q06"                   "Q01"                  
## [49] "FL_20_DO"              "CondControle_DO"       "CondHumana_DO"        
## [52] "Atitude_DO"            "ItensHumanização_DO"

Ops. Parece que a nomeação das variáveis tem um problema. O Qualtrics nos permite nomear variáveis. Eu recomendo que as nomes sejam sempre (1) diagnósticos: nos permitam saber exatamente do que se trata a variável sem precisar recorrer ao questionário ou dicionário de variáveis e (2) simples: o menor número de caracteres possível (precisaremos digitar o nome das variáveis pelo menos uma vez), sem letras maiusculas (o R diferencia capitalização), sem acentuação (pode dar problema), não começando em números (o R não permite que objetos e variáveis tenham nomes que começam em números). Eu vou concertar os nomes das duas bases aqui. Eu li o questionário e destilei as características principais de cada variável.

nomes_corrigidos<-c("StartDate", "EndDate", "Status", "IPAddress", "Progress", 
                    "Duration", "Finished", "RecordedDate", "ResponseId", 
                    "RecipientLastName", "RecipientFirstName", "RecipientEmail",
                    "ExternalReference", "LocationLatitude", "LocationLongitude",
                    "DistributionChannel", "UserLanguage", "Consentimento", 
                    "a1_reputacao", "a2_cara", "a3_prestigio", "a4_qualidade", 
                    "a5_gosto", "a6_melhor", "a7_admiro", "a8_simpatia", 
                    "a9_compraria", "a10_recomendaria", "a11_prefiro", 
                    "h1_homens", "h2_humanas", "h3_amigos", "h4_personalidade", 
                    "h5_atraente", "h6_medo", "h7_emocional", "h8_aberta", 
                    "h9_etica", "humanizada", "genero", "idade", "escolaridade", 
                    "freq_twitter", "freq_instagram", "freq_facebook", 
                    "sabia_humanizada", "comentário", "sorteio", "condicao", 
                    "CondControle_DO", "CondHumana_DO", "Atitude_DO", 
                    "ItensHumanização_DO")
#ver se o número de variáveis nas bases "match" o número de variáveis que eu digitei
length(names(dt))
## [1] 53
length(names(dn))
## [1] 53
length(nomes_corrigidos)
## [1] 53
#já que eles todos têm o mesmo número de elementos
names(dt)<-nomes_corrigidos
names(dn)<-nomes_corrigidos

Limpeza da base de dados

Agora sim, limpando a base de dados. Como eu havia comentado, a minha aluna rodou o estudo duas vezes e deixou esses dados na base. Precisamos eliminar.

names(dt)
##  [1] "StartDate"           "EndDate"             "Status"             
##  [4] "IPAddress"           "Progress"            "Duration"           
##  [7] "Finished"            "RecordedDate"        "ResponseId"         
## [10] "RecipientLastName"   "RecipientFirstName"  "RecipientEmail"     
## [13] "ExternalReference"   "LocationLatitude"    "LocationLongitude"  
## [16] "DistributionChannel" "UserLanguage"        "Consentimento"      
## [19] "a1_reputacao"        "a2_cara"             "a3_prestigio"       
## [22] "a4_qualidade"        "a5_gosto"            "a6_melhor"          
## [25] "a7_admiro"           "a8_simpatia"         "a9_compraria"       
## [28] "a10_recomendaria"    "a11_prefiro"         "h1_homens"          
## [31] "h2_humanas"          "h3_amigos"           "h4_personalidade"   
## [34] "h5_atraente"         "h6_medo"             "h7_emocional"       
## [37] "h8_aberta"           "h9_etica"            "humanizada"         
## [40] "genero"              "idade"               "escolaridade"       
## [43] "freq_twitter"        "freq_instagram"      "freq_facebook"      
## [46] "sabia_humanizada"    "comentário"          "sorteio"            
## [49] "condicao"            "CondControle_DO"     "CondHumana_DO"      
## [52] "Atitude_DO"          "ItensHumanização_DO"

E a variável sorteio. Vamos ver onde esses casos estão

head(dt$sorteio)
## [1] "KAREN - DESCONSIDERAR"   "KAREN 2 - DESCONSIDERAR"
## [3] "51991838706"             "51998036343"            
## [5] "51980424234"             "51 997799888"

São os dois primeiros casos. Vamos elimina-los das duas bases de dados. Eu vou criar uma base nova, sem esses dois casos. Eu não vou manter o mesmo nome, do contrário a base pode ser corrompida múltiplas vezes. Existem várias formas de fazer isso. Eu posso pedir para o R eliminar os casos cujas respostas para a variável sorteio são “KAREN - DESCONSIDERAR” e “KAREN 2 - DESCONSIDERAR” respectivamente. Ou, nesse caso, posso pedir só para apagar os dois primeiros casos. Daqui em diante usarei só a base “dt” que tem números nas escalas e texto quando apropriado.

d<-dt[-c(1,2),]
head(d$sorteio)
## [1] "51991838706"                  "51998036343"                 
## [3] "51980424234"                  "51 997799888"                
## [5] "brunalimalampert@hotmail.com" "sinhorellivictoria@gmail.com"

Eu quero verificar quem acabou o questionário. Para isso, eu farei uma tabela e a colocarei em um formato mais amigável usando uma função do markdown, Kable.

require(knitr)
require(questionr)
table(d$Finished)
## 
## FALSE  TRUE 
##   125   199
d$Acabou<-factor(d$Finished, levels = c("FALSE","TRUE"), labels = c("Não","Sim"))
t.acabou<-freq(d$Acabou, digits = 2, exclude = NA, total = T)
kable(t.acabou, caption = "Quantos acabaram o questionário")
Quantos acabaram o questionário
n %
Não 125 38.58
Sim 199 61.42
Total 324 100.00

Muita gente não acabou o questionário. Muitos respondentes não inseriram o email ou telefone para o sorteio, outros não enviaram o questionário. TODOS os testes que eu farei aqui eliminam missings do processo de análise, e as não respostas acabariam sendo eliminadas. Mesmo assim, eu eliminarei os que não acabaram o questionário da amostra.

d.finished<-subset(d, d$Acabou == "Sim")

Agora é uma boa oportunidade para darmos uma olhada nos outliers em tempo de resposta. A aluna não utilizou nenhuma “instructional manipulation checks”, então essa é a única medida de atenção que podemos utilizar. É importante que façamos isso no começo. Se determinarmos que o tempo de resposta é uma medida diagnóstica de atenção ou de falta de comprometimento, e esse for um critério de deleção, devemos fazer isso antes de ver os resultados e de forma consistente em todas as bases investigadas.

d.finished$log_duration<-log(d.finished$Duration)
tempo<-boxplot(d.finished$log_duration)

sort(tempo$out)
##  [1] 7.049255 7.125283 7.282761 7.731053 7.780303 7.872455 8.074649 8.149313
##  [9] 8.574329 8.617762 9.110410
do<-subset(d.finished, (d.finished$log_duration < 7.049))

Criando Variáveis Compostas para Atitude e Marca Humanizada

Aqui eu criarei variáveis compostas (médias) para Atitude e Humanização da Marca e extrairei o Alfa de Cronbach.

do$atitude.df <- data.frame(do$a1_reputacao, do$a2_cara, do$a3_prestigio, 
                            do$a4_qualidade, do$a5_gosto, do$a6_melhor,
                            do$a7_admiro, do$a8_simpatia, do$a9_compraria, 
                            do$a10_recomendaria, do$a11_prefiro)
do$atitude<-rowMeans(do$atitude.df, na.rm = TRUE)

do$human.df <- data.frame(do$h1_homens, do$h2_humanas, do$h3_amigos, do$h4_personalidade, 
                          do$h5_atraente, do$h6_medo, do$h7_emocional, do$h8_aberta, 
                          do$h9_etica)
do$human <- rowMeans(do$human.df, na.rm = TRUE)

require(psych)
alpha(do$atitude.df)
## 
## Reliability analysis   
## Call: alpha(x = do$atitude.df)
## 
##   raw_alpha std.alpha G6(smc) average_r S/N    ase mean sd median_r
##       0.96      0.96    0.96      0.66  21 0.0042  2.3  1     0.74
## 
##  lower alpha upper     95% confidence boundaries
## 0.95 0.96 0.97 
## 
##  Reliability if an item is dropped:
##                     raw_alpha std.alpha G6(smc) average_r S/N alpha se  var.r
## do.a1_reputacao          0.95      0.95    0.96      0.65  18   0.0049 0.0495
## do.a2_cara               0.97      0.97    0.97      0.76  32   0.0033 0.0017
## do.a3_prestigio          0.95      0.95    0.96      0.65  19   0.0047 0.0518
## do.a4_qualidade          0.95      0.95    0.96      0.66  19   0.0046 0.0528
## do.a5_gosto              0.95      0.95    0.96      0.65  18   0.0049 0.0499
## do.a6_melhor             0.95      0.95    0.96      0.65  19   0.0047 0.0507
## do.a7_admiro             0.95      0.95    0.96      0.65  19   0.0048 0.0500
## do.a8_simpatia           0.95      0.95    0.96      0.65  18   0.0049 0.0480
## do.a9_compraria          0.95      0.95    0.96      0.65  19   0.0047 0.0514
## do.a10_recomendaria      0.95      0.95    0.96      0.65  19   0.0048 0.0498
## do.a11_prefiro           0.95      0.95    0.96      0.65  19   0.0047 0.0512
##                     med.r
## do.a1_reputacao      0.74
## do.a2_cara           0.76
## do.a3_prestigio      0.75
## do.a4_qualidade      0.76
## do.a5_gosto          0.74
## do.a6_melhor         0.74
## do.a7_admiro         0.74
## do.a8_simpatia       0.74
## do.a9_compraria      0.74
## do.a10_recomendaria  0.74
## do.a11_prefiro       0.74
## 
##  Item statistics 
##                       n raw.r std.r r.cor r.drop mean  sd
## do.a1_reputacao     188  0.90  0.90  0.89   0.87  2.4 1.4
## do.a2_cara          188  0.32  0.34  0.25   0.24  2.6 1.0
## do.a3_prestigio     188  0.87  0.87  0.86   0.84  2.2 1.2
## do.a4_qualidade     188  0.84  0.84  0.83   0.81  2.2 1.1
## do.a5_gosto         188  0.91  0.90  0.90   0.88  2.4 1.3
## do.a6_melhor        188  0.87  0.87  0.86   0.84  2.1 1.1
## do.a7_admiro        188  0.89  0.88  0.88   0.86  2.2 1.3
## do.a8_simpatia      188  0.91  0.90  0.90   0.88  2.5 1.4
## do.a9_compraria     188  0.88  0.88  0.87   0.85  2.3 1.3
## do.a10_recomendaria 188  0.89  0.89  0.88   0.87  2.2 1.3
## do.a11_prefiro      188  0.87  0.87  0.86   0.84  2.0 1.1
## 
## Non missing response frequency for each item
##                        1    2    3    4    5 miss
## do.a1_reputacao     0.36 0.19 0.19 0.17 0.09    0
## do.a2_cara          0.18 0.22 0.44 0.14 0.02    0
## do.a3_prestigio     0.37 0.23 0.22 0.16 0.02    0
## do.a4_qualidade     0.31 0.26 0.32 0.09 0.02    0
## do.a5_gosto         0.34 0.21 0.26 0.13 0.06    0
## do.a6_melhor        0.45 0.17 0.28 0.06 0.04    0
## do.a7_admiro        0.42 0.18 0.21 0.13 0.06    0
## do.a8_simpatia      0.38 0.16 0.17 0.18 0.11    0
## do.a9_compraria     0.40 0.17 0.24 0.13 0.05    0
## do.a10_recomendaria 0.43 0.20 0.21 0.11 0.06    0
## do.a11_prefiro      0.48 0.18 0.23 0.08 0.03    0
alpha(do$human.df)
## 
## Reliability analysis   
## Call: alpha(x = do$human.df)
## 
##   raw_alpha std.alpha G6(smc) average_r S/N    ase mean  sd median_r
##       0.96      0.95    0.96       0.7  21 0.0045  2.8 1.3     0.72
## 
##  lower alpha upper     95% confidence boundaries
## 0.95 0.96 0.96 
## 
##  Reliability if an item is dropped:
##                     raw_alpha std.alpha G6(smc) average_r S/N alpha se var.r
## do.h1_homens             0.96      0.96    0.96      0.74  23   0.0042 0.013
## do.h2_humanas            0.95      0.95    0.95      0.69  18   0.0054 0.018
## do.h3_amigos             0.95      0.94    0.95      0.68  17   0.0056 0.015
## do.h4_personalidade      0.95      0.95    0.96      0.71  19   0.0049 0.021
## do.h5_atraente           0.96      0.96    0.96      0.74  23   0.0043 0.015
## do.h6_medo               0.95      0.95    0.95      0.69  18   0.0054 0.015
## do.h7_emocional          0.95      0.95    0.95      0.69  18   0.0054 0.019
## do.h8_aberta             0.95      0.95    0.95      0.68  17   0.0056 0.015
## do.h9_etica              0.95      0.95    0.95      0.70  18   0.0052 0.019
##                     med.r
## do.h1_homens         0.77
## do.h2_humanas        0.67
## do.h3_amigos         0.67
## do.h4_personalidade  0.75
## do.h5_atraente       0.77
## do.h6_medo           0.69
## do.h7_emocional      0.67
## do.h8_aberta         0.67
## do.h9_etica          0.70
## 
##  Item statistics 
##                       n raw.r std.r r.cor r.drop mean  sd
## do.h1_homens        188  0.68  0.70  0.65   0.62  2.6 1.2
## do.h2_humanas       188  0.91  0.91  0.90   0.89  2.7 1.6
## do.h3_amigos        188  0.94  0.93  0.93   0.92  2.8 1.7
## do.h4_personalidade 188  0.84  0.84  0.81   0.79  2.8 1.4
## do.h5_atraente      188  0.71  0.72  0.67   0.65  2.7 1.3
## do.h6_medo          188  0.91  0.90  0.90   0.88  3.0 1.8
## do.h7_emocional     188  0.91  0.91  0.90   0.88  2.8 1.6
## do.h8_aberta        188  0.93  0.92  0.93   0.91  2.9 1.8
## do.h9_etica         188  0.88  0.88  0.86   0.85  2.6 1.4
## 
## Non missing response frequency for each item
##                        1    2    3    4    5 miss
## do.h1_homens        0.27 0.18 0.34 0.14 0.08    0
## do.h2_humanas       0.37 0.11 0.16 0.18 0.18    0
## do.h3_amigos        0.44 0.04 0.11 0.15 0.26    0
## do.h4_personalidade 0.27 0.19 0.19 0.21 0.14    0
## do.h5_atraente      0.28 0.16 0.28 0.18 0.10    0
## do.h6_medo          0.40 0.07 0.04 0.13 0.36    0
## do.h7_emocional     0.33 0.12 0.15 0.20 0.20    0
## do.h8_aberta        0.40 0.07 0.05 0.17 0.31    0
## do.h9_etica         0.34 0.12 0.27 0.16 0.11    0

Vamos inspecionar as médias de atitude e médias de “humanização” da marca por condição. Mas antes disso, quantos casos temos por condição mesmo?

table(do$condicao)
## 
## CondControle   CondHumana 
##           91           97
#fazendo mais "bonito"

do$condicoes <- factor(do$condicao, levels = c("CondControle", "CondHumana"), 
                       labels = c("Controle", "Humanizada"))
t.condicao <- freq(do$condicoes, digits = 2, exclude = NA, total = T)
kable(t.condicao, caption = "Respondentes por Condição")
Respondentes por Condição
n %
Controle 91 48.4
Humanizada 97 51.6
Total 188 100.0

Mais ou menos equilibradas as condições. Agora vamos ver como as variáveis de interesse se distribuem por condições. Para isso, eu vou usar a função “describeBy”, do pacote psych.

desc.atitude <- describeBy(do$atitude,do$condicoes, mat = T, digits = 2)
names(desc.atitude)[2] <- "Condições"
row.names(desc.atitude)<-NULL
desc.human <- describeBy(do$human,do$condicoes, mat = T, digits = 2)
names(desc.human)[2] <- "Condições"
row.names(desc.human)<-NULL

desc.atitude
desc.human
kable(desc.atitude[,c(2,4:6)], caption = "Médias de Atitude por Condição Experimental")
Médias de Atitude por Condição Experimental
Condições n mean sd
Controle 91 1.63 0.65
Humanizada 97 2.89 0.93
kable(desc.human[,c(2,4:6)], caption = "Médias de Humanização por Condição Experimental")
Médias de Humanização por Condição Experimental
Condições n mean sd
Controle 91 1.64 0.71
Humanizada 97 3.79 0.81

Podemos, também, fazer gráficos, mas as informações são redundantes.

require(ggplot2)

ggplot(desc.atitude, aes(x=`Condições`, y=mean))+
  geom_bar(stat = "identity", width = 0.5, fill = "lightblue")+
  geom_errorbar(aes(ymax = mean + (1.96*se), ymin=mean - (1.96*se)), 
                position=position_dodge(width=0.9), width=0.25)+
  # coord_cartesian(ylim = c(1, 3))+
  labs(title="Atitude em Relação à Marca por Condição Experimental", 
       y="Atitude Média", x="Condições")

ggplot(desc.human, aes(x=`Condições`, y=mean))+
  geom_bar(stat = "identity", width = 0.5, fill = "pink")+
  geom_errorbar(aes(ymax = mean + (1.96*se), ymin=mean - (1.96*se)), 
                position=position_dodge(width=0.9), width=0.25)+
  # coord_cartesian(ylim = c(1, 3))+
  labs(title="Humanização da Marca por Condição Experimental", 
       y="Humanização Média", x="Condições")

Relações entre as Variáveis

Agora finalmente entramos nos testes de hipóteses. Recapitulando: H1: A atitude em relação a marcas humanizadas é mais alta (mais positiva) quando comparada a marcas “tradicionais” (controle) H2: A intenção de compra de marcas humanizadas é mais alta do que a de marcas tradicionais (controle) H3: Marcas humanizadas são consideradas “mais humanas” do que marcas tradicionais (controle) H4: A influência das marcas humanizadas na atitude em relação à marca é moderada pela idade do respondente.

H1 - Atitude e Marca Humanizada

Para esse teste de hipóteses e para os a seguir, testaremos a mesma hipótese de diferentes formas: teste t, ANOVA e Regressão Linear. Para cada um dos testes, faremos os diagnósticos necessários.

H1 - Teste T

Pressupostos. Como veremos, o teste t é, em suma, um modelo linear generalizado (GLM). Já trabalhamos com essa ideia em aula, mas a lógica das “distâncias” ou diferenças entre médias e a lógica da OLS, ordinary least squares, é a mesma. Dessa forma, os pressupostos são os mesmos. Normalidade dos resíduos e homogeneidade da variância. No teste t, a diferença entre os grupos deve seguir uma distribuição normal. Já homogeneidade da variância só é uma preocupação quando o tamanho (n) dos grupos é muito diferente. Nesses casos, o teste de Lavene, usado para isso, não é muito funcional. A ideia é usar um teste t de Welch que corrige para violações de homogeneidade da variância (Field et al., 2012). Para nossa sorte, esse é o teste t default do R. Vamos começar visualizando os grupos.

ggplot(do, aes(x=condicoes,y=atitude, fill=condicoes)) +
  geom_violin(trim=FALSE) +
  stat_summary(fun.data=mean_sdl, fun.args = list(mult = 1),
                 geom="pointrange", color="white") +
  coord_cartesian(ylim = c(0,6)) +
  labs(title = "Atitude por Condições", x = "Condições Experimentais", 
       y = "Atitude", fill = "Condições")

Faremos um teste de Shapiro Wilk para normalidade. Procuramos um p > .05.

require(pastecs)
shapiro.test(do$atitude[do$condicoes=="Humanizada"])
## 
##  Shapiro-Wilk normality test
## 
## data:  do$atitude[do$condicoes == "Humanizada"]
## W = 0.97149, p-value = 0.0329
shapiro.test(do$atitude[do$condicoes=="Controle"])
## 
##  Shapiro-Wilk normality test
## 
## data:  do$atitude[do$condicoes == "Controle"]
## W = 0.84404, p-value = 2.296e-08
by(do$atitude, do$condicoes, stat.desc, basic = FALSE, norm = TRUE)
## do$condicoes: Controle
##       median         mean      SE.mean CI.mean.0.95          var      std.dev 
## 1.363636e+00 1.631369e+00 6.825467e-02 1.355998e-01 4.239417e-01 6.511081e-01 
##     coef.var     skewness     skew.2SE     kurtosis     kurt.2SE   normtest.W 
## 3.991177e-01 1.312945e+00 2.598075e+00 1.245823e+00 1.245069e+00 8.440358e-01 
##   normtest.p 
## 2.295567e-08 
## ------------------------------------------------------------ 
## do$condicoes: Humanizada
##       median         mean      SE.mean CI.mean.0.95          var      std.dev 
##   3.09090909   2.88847235   0.09438175   0.18734629   0.86406769   0.92955241 
##     coef.var     skewness     skew.2SE     kurtosis     kurt.2SE   normtest.W 
##   0.32181454  -0.23122436  -0.47193406  -0.68528264  -0.70599696   0.97148818 
##   normtest.p 
##   0.03289711
do$trans_atitude <- log(do$atitude) #sqrt(do$atitude) 1/(do$atitude)

qplot(sample = atitude, data = do, color=condicoes) +
  labs(title = "QQPlot para Atitude e Condições")

Os dados para atitude são não-normais. Nos temos duas opções: ou nós tentamos transformar os dados ou rodamos análises não paramétricas. Muitos pesquisadores só ignoram isso e rodam o t-test da mesma forma. Faremos tudo aqui.

t.test(atitude ~ condicoes, data = do)
## 
##  Welch Two Sample t-test
## 
## data:  atitude by condicoes
## t = -10.793, df = 172.38, p-value < 2.2e-16
## alternative hypothesis: true difference in means between group Controle and group Humanizada is not equal to 0
## 95 percent confidence interval:
##  -1.487006 -1.027201
## sample estimates:
##   mean in group Controle mean in group Humanizada 
##                 1.631369                 2.888472
require(effsize)
effsize::cohen.d(do$atitude, do$condicoes)
## 
## Cohen's d
## 
## d estimate: -1.557923 (large)
## 95 percent confidence interval:
##     lower     upper 
## -1.886579 -1.229268
kruskal.test(atitude ~ condicoes, data = do)
## 
##  Kruskal-Wallis rank sum test
## 
## data:  atitude by condicoes
## Kruskal-Wallis chi-squared = 71.175, df = 1, p-value < 2.2e-16
require(rstatix)
kruskal_effsize(atitude ~ condicoes, data = do)

As análises seguintes ficam redundantes, pois já encontramos a resposta, a atitude é mais positiva para a marca humanizada. Mas vamos ao exercício.

H1 - ANOVA

A ANOVA é um teste mais robusto. Existe muito debate sobre isso e sobre os efeitos da (não)normalidade. Quando os grupos são equivalentes, ANOVA é robusta para violações da homogeneidade da variância. O que é o caso, aliás - identificado por um teste de Levene, testando a diferença das variâncias. Queremos que as variâncias não sejam diferentes, ou seja, que p > 0.05.

require(car)
leveneTest(do$atitude, do$condicoes)
leveneTest(log(do$atitude), do$condicoes)

Todo caso, homogeneidade da variância responde bem a transformações das variáveis. Vamos usar o log da atitude também.

h1.anova <- aov(atitude ~ condicoes, data = do)
summary(h1.anova)
##              Df Sum Sq Mean Sq F value Pr(>F)    
## condicoes     1   74.2   74.20     114 <2e-16 ***
## Residuals   186  121.1    0.65                   
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
h1.anova.log <- aov(log(atitude) ~ condicoes, data = do)
summary(h1.anova.log)
##              Df Sum Sq Mean Sq F value Pr(>F)    
## condicoes     1  15.54  15.536   115.7 <2e-16 ***
## Residuals   186  24.97   0.134                   
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Em ambos os casos, a H1 foi confirmada.

H1 - Regressão Linear

A lógica da regressão é similar a da ANOVA. Mas é muito útil quando começamos a trabalhar com códigos de contraste, spotlights e outras relações mais complexas entre as variáveis. A primeira coisa que precisamos fazer para rodar uma regressão é codificar as nossas condições experimentais em códigos de contraste centrados em zero. Leremos mais adiante porque isso é importante (zero é mágico!).

do$condicoes.cc[do$condicoes=="Controle"] <- -1
do$condicoes.cc[do$condicoes=="Humanizada"] <- +1
table(do$condicoes,do$condicoes.cc) #funcionou
##             
##              -1  1
##   Controle   91  0
##   Humanizada  0 97

Como existem violações dos pressupostos da regressão, deveríamos rodar um teste não paramétrico (Kruskal-Wallis). Já o fizemos. Vamos rodar um modelo com atitude e com log(atitude). Primeiro a regressão com atitude original.

h1.reg <- lm(atitude ~ condicoes.cc, data = do)
plot(h1.reg, which = c(2))

summary(h1.reg)
## 
## Call:
## lm(formula = atitude ~ condicoes.cc, data = do)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -1.88847 -0.54046 -0.03265  0.46345  2.09590 
## 
## Coefficients:
##              Estimate Std. Error t value Pr(>|t|)    
## (Intercept)   2.25992    0.05888   38.38   <2e-16 ***
## condicoes.cc  0.62855    0.05888   10.68   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.8069 on 186 degrees of freedom
## Multiple R-squared:  0.3799, Adjusted R-squared:  0.3766 
## F-statistic:   114 on 1 and 186 DF,  p-value: < 2.2e-16

E agora com atitude log.

h1.reg.log <- lm(log(atitude) ~ condicoes.cc, data = do)
plot(h1.reg.log, which = c(2))

summary(h1.reg.log)
## 
## Call:
## lm(formula = log(atitude) ~ condicoes.cc, data = do)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -0.99808 -0.25580  0.05381  0.24161  0.89282 
## 
## Coefficients:
##              Estimate Std. Error t value Pr(>|t|)    
## (Intercept)   0.71047    0.02674   26.57   <2e-16 ***
## condicoes.cc  0.28761    0.02674   10.76   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.3664 on 186 degrees of freedom
## Multiple R-squared:  0.3835, Adjusted R-squared:  0.3802 
## F-statistic: 115.7 on 1 and 186 DF,  p-value: < 2.2e-16

H2 - Teste T

Eu vou repetir todos os procedimentos para H1, mas investigando apenas a9_compraria. Aqui entra o bom e velho copia-cola. Mas cuidado ao mudar o nome das variáveis.

ggplot(do, aes(x=condicoes,y=a9_compraria, fill=condicoes)) +
  geom_violin(trim=FALSE) +
  stat_summary(fun.data=mean_sdl, fun.args = list(mult = 1),
                 geom="pointrange", color="white") +
  coord_cartesian(ylim = c(0,6)) +
  labs(title = "Intenção de Compra por Condições", x = "Condições Experimentais", 
       y = "Atitude", fill = "Condições")

Faremos um teste de Shapiro Wilk para normalidade. Procuramos um p > .05.

shapiro.test(do$a9_compraria[do$condicoes=="Humanizada"])
## 
##  Shapiro-Wilk normality test
## 
## data:  do$a9_compraria[do$condicoes == "Humanizada"]
## W = 0.89824, p-value = 1.599e-06
shapiro.test(do$a9_compraria[do$condicoes=="Controle"])
## 
##  Shapiro-Wilk normality test
## 
## data:  do$a9_compraria[do$condicoes == "Controle"]
## W = 0.66829, p-value = 4.952e-13
by(do$a9_compraria, do$condicoes, stat.desc, basic = FALSE, norm = TRUE)
## do$condicoes: Controle
##       median         mean      SE.mean CI.mean.0.95          var      std.dev 
## 1.000000e+00 1.604396e+00 1.023284e-01 2.032931e-01 9.528694e-01 9.761503e-01 
##     coef.var     skewness     skew.2SE     kurtosis     kurt.2SE   normtest.W 
## 6.084224e-01 1.694328e+00 3.352762e+00 2.279098e+00 2.277719e+00 6.682928e-01 
##   normtest.p 
## 4.952071e-13 
## ------------------------------------------------------------ 
## do$condicoes: Humanizada
##        median          mean       SE.mean  CI.mean.0.95           var 
##  3.000000e+00  2.896907e+00  1.194961e-01  2.371979e-01  1.385095e+00 
##       std.dev      coef.var      skewness      skew.2SE      kurtosis 
##  1.176900e+00  4.062610e-01 -1.439986e-01 -2.939043e-01 -7.639143e-01 
##      kurt.2SE    normtest.W    normtest.p 
## -7.870054e-01  8.982354e-01  1.599248e-06
do$trans_a9_compraria <- log(do$a9_compraria) #sqrt(do$a9_compraria) 1/(do$a9_compraria)

qplot(sample = a9_compraria, data = do, color=condicoes) +
  labs(title = "QQPlot para Intenção de Compra e Condições")

Os dados para a9_compraria (Intenção de Compra) são não-normais. Nos temos duas opções: ou nós tentamos transformar os dados ou rodamos análises não paramétricas. Muitos pesquisadores só ignoram isso e rodam o t-test da mesma forma. Faremos tudo aqui.

t.test(a9_compraria ~ condicoes, data = do)
## 
##  Welch Two Sample t-test
## 
## data:  a9_compraria by condicoes
## t = -8.2157, df = 183.29, p-value = 3.713e-14
## alternative hypothesis: true difference in means between group Controle and group Humanizada is not equal to 0
## 95 percent confidence interval:
##  -1.6029078 -0.9821154
## sample estimates:
##   mean in group Controle mean in group Humanizada 
##                 1.604396                 2.896907
require(effsize)
effsize::cohen.d(do$a9_compraria, do$condicoes)
## 
## Cohen's d
## 
## d estimate: -1.191899 (large)
## 95 percent confidence interval:
##      lower      upper 
## -1.5043031 -0.8794947
kruskal.test(a9_compraria ~ condicoes, data = do)
## 
##  Kruskal-Wallis rank sum test
## 
## data:  a9_compraria by condicoes
## Kruskal-Wallis chi-squared = 52.439, df = 1, p-value = 4.437e-13
require(rstatix)
kruskal_effsize(a9_compraria ~ condicoes, data = do)

As análises seguintes ficam redundantes, pois já encontramos a resposta, a intenção de compra é maior. Mas vamos ao exercício.

H2 - ANOVA

leveneTest(do$a9_compraria, do$condicoes)
leveneTest(log(do$a9_compraria), do$condicoes)

Todo caso, homogeneidade da variância responde bem a transformações das variáveis. Vamos usar o log da a9_compraria também.

h2.anova <- aov(a9_compraria ~ condicoes, data = do)
summary(h2.anova)
##              Df Sum Sq Mean Sq F value  Pr(>F)    
## condicoes     1  78.44   78.44    66.7 4.7e-14 ***
## Residuals   186 218.73    1.18                    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
h2.anova.log <- aov(log(a9_compraria) ~ condicoes, data = do)
summary(h2.anova.log)
##              Df Sum Sq Mean Sq F value   Pr(>F)    
## condicoes     1  17.96  17.963   72.96 4.67e-15 ***
## Residuals   186  45.79   0.246                     
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Em ambos os casos, a h2 foi confirmada.

h2 - Regressão Linear

Como existem violações dos pressupostos da regressão, deveríamos rodar um teste não paramétrico (Kruskal-Wallis). Já o fizemos. Vamos rodar um modelo com a9_compraria e com log(a9_compraria). Primeiro a regressão com a9_compraria original.

h2.reg <- lm(a9_compraria ~ condicoes.cc, data = do)
plot(h2.reg, which = c(2))

summary(h2.reg)
## 
## Call:
## lm(formula = a9_compraria ~ condicoes.cc, data = do)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -1.8969 -0.6044  0.1031  0.3956  3.3956 
## 
## Coefficients:
##              Estimate Std. Error t value Pr(>|t|)    
## (Intercept)   2.25065    0.07913  28.443  < 2e-16 ***
## condicoes.cc  0.64626    0.07913   8.167  4.7e-14 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 1.084 on 186 degrees of freedom
## Multiple R-squared:  0.264,  Adjusted R-squared:   0.26 
## F-statistic:  66.7 on 1 and 186 DF,  p-value: 4.697e-14

E agora com a9_compraria log.

h2.reg.log <- lm(log(a9_compraria) ~ condicoes.cc, data = do)
plot(h2.reg.log, which = c(2))

summary(h2.reg.log)
## 
## Call:
## lm(formula = log(a9_compraria) ~ condicoes.cc, data = do)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -0.9561 -0.3376  0.1425  0.3555  1.2718 
## 
## Coefficients:
##              Estimate Std. Error t value Pr(>|t|)    
## (Intercept)   0.64688    0.03621  17.867  < 2e-16 ***
## condicoes.cc  0.30927    0.03621   8.542 4.67e-15 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.4962 on 186 degrees of freedom
## Multiple R-squared:  0.2818, Adjusted R-squared:  0.2779 
## F-statistic: 72.96 on 1 and 186 DF,  p-value: 4.672e-15

Testaremos a Hipótese H3

H3 - Teste T

Eu vou repetir todos os procedimentos para H1, mas investigando apenas a humanização da marca. Aqui entra o bom e velho copia-cola. Mas cuidado ao mudar o nome das variáveis.

ggplot(do, aes(x=condicoes,y=human, fill=condicoes)) +
  geom_violin(trim=FALSE) +
  stat_summary(fun.data=mean_sdl, fun.args = list(mult = 1),
                 geom="pointrange", color="white") +
  coord_cartesian(ylim = c(0,6)) +
  labs(title = "Humanização por Condições", x = "Condições Experimentais", 
       y = "Atitude", fill = "Condições")

Faremos um teste de Shapiro Wilk para normalidade. Procuramos um p > .05.

shapiro.test(do$human[do$condicoes=="Humanizada"])
## 
##  Shapiro-Wilk normality test
## 
## data:  do$human[do$condicoes == "Humanizada"]
## W = 0.9528, p-value = 0.001557
shapiro.test(do$human[do$condicoes=="Controle"])
## 
##  Shapiro-Wilk normality test
## 
## data:  do$human[do$condicoes == "Controle"]
## W = 0.81614, p-value = 2.779e-09
by(do$human, do$condicoes, stat.desc, basic = FALSE, norm = TRUE)
## do$condicoes: Controle
##       median         mean      SE.mean CI.mean.0.95          var      std.dev 
## 1.444444e+00 1.642247e+00 7.459730e-02 1.482006e-01 5.063929e-01 7.116129e-01 
##     coef.var     skewness     skew.2SE     kurtosis     kurt.2SE   normtest.W 
## 4.333167e-01 1.610958e+00 3.187789e+00 2.554508e+00 2.552962e+00 8.161443e-01 
##   normtest.p 
## 2.778908e-09 
## ------------------------------------------------------------ 
## do$condicoes: Humanizada
##       median         mean      SE.mean CI.mean.0.95          var      std.dev 
##  3.888888889  3.790378007  0.082483838  0.163729125  0.659947605  0.812371593 
##     coef.var     skewness     skew.2SE     kurtosis     kurt.2SE   normtest.W 
##  0.214324690 -0.779170091 -1.590303480  0.616086759  0.634709463  0.952798929 
##   normtest.p 
##  0.001557108
do$trans_human <- log(do$human) #sqrt(do$human) 1/(do$human)

qplot(sample = human, data = do, color=condicoes) +
  labs(title = "QQPlot para Intenção de Compra e Condições")

Os dados para human (Intenção de Compra) são não-normais. Nos temos duas opções: ou nós tentamos transformar os dados ou rodamos análises não paramétricas. Muitos pesquisadores só ignoram isso e rodam o t-test da mesma forma. Faremos tudo aqui.

t.test(human ~ condicoes, data = do)
## 
##  Welch Two Sample t-test
## 
## data:  human by condicoes
## t = -19.315, df = 185.15, p-value < 2.2e-16
## alternative hypothesis: true difference in means between group Controle and group Humanizada is not equal to 0
## 95 percent confidence interval:
##  -2.367539 -1.928724
## sample estimates:
##   mean in group Controle mean in group Humanizada 
##                 1.642247                 3.790378
effsize::cohen.d(do$human, do$condicoes)
## 
## Cohen's d
## 
## d estimate: -2.807003 (large)
## 95 percent confidence interval:
##     lower     upper 
## -3.212526 -2.401480
kruskal.test(human ~ condicoes, data = do)
## 
##  Kruskal-Wallis rank sum test
## 
## data:  human by condicoes
## Kruskal-Wallis chi-squared = 116.73, df = 1, p-value < 2.2e-16
kruskal_effsize(human ~ condicoes, data = do)

As análises seguintes ficam redundantes, pois já encontramos a resposta, a humanização é maior para marcas humanizadas. Mas vamos ao exercício.

H3 - ANOVA

leveneTest(do$human, do$condicoes)

O pressuposto da homogeneidade da variância não foi violado. Seguimos com a ANOVA.

h3.anova <- aov(human ~ condicoes, data = do)
summary(h3.anova)
##              Df Sum Sq Mean Sq F value Pr(>F)    
## condicoes     1  216.7  216.66   369.9 <2e-16 ***
## Residuals   186  108.9    0.59                   
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Em ambos os casos, a h3 foi confirmada.

H3 - Regressão Linear

h3.reg <- lm(human ~ condicoes.cc, data = do)
plot(h3.reg, which = c(2))

summary(h3.reg)
## 
## Call:
## lm(formula = human ~ condicoes.cc, data = do)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -2.79038 -0.56816 -0.08669  0.44110  2.46886 
## 
## Coefficients:
##              Estimate Std. Error t value Pr(>|t|)    
## (Intercept)   2.71631    0.05584   48.64   <2e-16 ***
## condicoes.cc  1.07407    0.05584   19.23   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.7653 on 186 degrees of freedom
## Multiple R-squared:  0.6654, Adjusted R-squared:  0.6636 
## F-statistic: 369.9 on 1 and 186 DF,  p-value: < 2.2e-16

Testando a H4

Como a H4 é uma hipótese de interação, não podemos fazer um teste T, mas podemos fazer uma ANOVA e uma regressão. O primeiro passo é centrar a idade na média, por razões que veremos na disciplina a seguir. Deveríamos fazer isso, mas como nossas condições estão equilibradas, o código de contraste usado naturalmente “centrou” na média.

do$idade.mc <- do$idade-mean(do$idade, na.rm = T)
mean(do$condicoes.cc)
## [1] 0.03191489
mean(do$idade.mc)
## [1] 1.499129e-16

Em seguida, podemos dar uma olhada na interação. É sempre mais fácil fazer o gráfico da variável contínua (de razão) no eixo dos X e a discreta (condição) como diferentes linhas. Isso é fácil no R.

ggplot(do) +
  aes(x = idade, y = atitude, color = condicoes) +
  geom_smooth(method = "lm")+
  labs (title = "Relação entre Idade, Condições e Atitude", x = "Idade (em anos)", 
        y = "Atitude em Relação à Marca", color = "Condições")

Testando a H4 via ANOVA

h4.anova <- aov (atitude ~ condicoes*idade, data = do)
summary(h4.anova)
##                  Df Sum Sq Mean Sq F value Pr(>F)    
## condicoes         1  74.20   74.20 115.486 <2e-16 ***
## idade             1   2.24    2.24   3.490 0.0633 .  
## condicoes:idade   1   0.64    0.64   1.004 0.3177    
## Residuals       184 118.22    0.64                   
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Testando a H4 via Regressão

h4.reg <- lm(atitude ~ condicoes*idade, data = do)
plot(h4.reg, which = c(2))

summary(h4.reg)
## 
## Call:
## lm(formula = atitude ~ condicoes * idade, data = do)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -1.94428 -0.54037 -0.06266  0.46481  2.09212 
## 
## Coefficients:
##                            Estimate Std. Error t value Pr(>|t|)    
## (Intercept)                1.743500   0.275680   6.324 1.88e-09 ***
## condicoesHumanizada        1.593056   0.359439   4.432 1.60e-05 ***
## idade                     -0.003870   0.009061  -0.427    0.670    
## condicoesHumanizada:idade -0.011821   0.011799  -1.002    0.318    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.8016 on 184 degrees of freedom
## Multiple R-squared:  0.3947, Adjusted R-squared:  0.3848 
## F-statistic: 39.99 on 3 and 184 DF,  p-value: < 2.2e-16