Pregătirea datelor: Măsurarea personalității cu 16 factori a lui Cattell

URMĂREȘTE-NE
16,065FaniÎmi place
1,142CititoriConectați-vă

(Acest articol a fost publicat pentru prima dată pe Profund Trivialși cu amabilitate a contribuit la R-bloggeri). (Puteți raporta problema legată de conținutul acestei pagini aici)


Doriți să vă distribuiți conținutul pe R-bloggeri? dați clic aici dacă aveți un blog, sau aici dacă nu aveți.

Așa cum am spus în postarea mea anterioară, lucrez la o serie din 2 părți în care arăt cum să efectuez analize psihometrice pe o măsură de personalitate. Acele postări vor veni foarte curând, dar astăzi, am vrut să încep prin a demonstra cum pregătesc datele pentru analiza psihometrice. Deci, să începem să lucrăm cu Masura de personalitate cu 16 factori a Cattell, sau mai precis, elementele din grupul internațional de articole de personalitate (IPIP) selectate pentru a reflecta cei 16 factori identificați de Cattell. Am întâlnit această măsură în timp ce exploram site-ul web Open-Source Psychometrics Project, care nu numai că vă permite să luați o mare varietate de măsuri de personalitate, ci și ca datele colectate prin intermediul site-ului să fie disponibile gratuit. Aceasta ar fi o sursă excelentă de folosit pentru un proiect de clasă, cineva care învață psihometrie sau care lucrează cu seturi de date mai mari… sau o postare pe blog! Când descărcați datele, veți primi și agenda de coduri a măsurii inclusă în fișierul zip. Cu toate acestea, cartea de coduri este într-adevăr un dicționar de date al elementelor din setul de date (nume, definiție și modul în care este codificat) și nu vă spune ce elemente sunt evaluate invers. Așa că am recomandat și această pagină, care listează elementele fiecărei măsuri în ordine, arătând care sunt tastate invers, precum și alfa pentru fiecare scală din cercetarea inițială. De asemenea, vă recomandăm să consultați această pagină pentru detalii suplimentare despre măsură. Când efectuați analize psihometrice, este posibil să aveți sau nu nevoie să faceți o curățare a datelor. Depinde cu adevărat de modul în care au fost colectate datele – a fost într-un cadru controlat, ca un centru de testare? Sau mai puțin controlat ca – în cazul acestei măsuri – un sondaj online? Probabil că avem date lipsă, deoarece niciunul dintre elemente nu a fost necesar. Am putea avea, de asemenea, răspunsuri în linie dreaptă (în cazul în care o persoană selectează același răspuns pentru fiecare item) sau răspunsuri fără sens la întrebarea de vârstă cu răspuns deschis, cum ar fi un respondent care a introdus 2.147.483.647, care și-ar pune nașterea chiar în mijlocul erei paleoproterozoice, când singurele ființe vii de pe planetă erau cele care aveau nevoie de oxigen. Deci haideți să ne încărcăm datele și să începem cu curățarea.

library(tidyverse)
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr     1.2.1     ✔ readr     2.2.0
## ✔ forcats   1.0.1     ✔ stringr   1.6.0
## ✔ ggplot2   4.0.3     ✔ tibble    3.3.1
## ✔ lubridate 1.9.5     ✔ tidyr     1.3.2
## ✔ purrr     1.2.2     
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag()    masks stats::lag()
## ℹ Use the conflicted package () to force all conflicts to become errors
library(ggthemes)

PF16 <- read_tsv("data.csv")
## Rows: 49159 Columns: 169
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: "t"
## chr   (1): country
## dbl (168): A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, B1, B2, B3, B4, B5, B6, ...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.

Potrivit documentației de pe site-ul web, aceștia au scos din setul descărcabil pe oricine sub 13 ani, precum și pe oricine care nu dorea ca datele lor să fie incluse. Dar mai sunt copii în platou (13 – 17), și, de asemenea, ființele noastre nemuritoare (adică, 2 miliarde de ani). Cu siguranță dorim să eliminăm acele rânduri din date, deoarece un răspuns aleatoriu la întrebarea privind vârsta ar putea însemna și răspunsuri aleatorii pentru restul măsurătorii. Așadar, haideți să obținem câteva date descriptive despre măsura noastră de vârstă și să luăm decizii despre cine să păstrăm și pe cine să filtram.

PF16 %>%
  filter(age > 99) %>%
  group_by(age) %>%
  summarise(count = n())
## # A tibble: 63 × 2
##      age count
##     
##  1   100     5
##  2   101     2
##  3   102     1
##  4   118     1
##  5   141     1
##  6   147     1
##  7   158     1
##  8   181     1
##  9   188     1
## 10   193     1
## # ℹ 53 more rows

Am căutat ceva pe Google, iar cea mai în vârstă persoană care a trăit vreodată (înregistrată) a avut 122 de ani, iar cea mai în vârstă persoană care încă trăiește are 117. Înclin să spun că oricine de peste 102 nu este sincer, așa că vom planifica să le eliminăm. Probabil că mulți oameni nu au fost sinceri cu privire la vârstă, dar dacă nu avem dovezi directe că mint, va trebui să-i lăsăm. Cu respondenții rămași, le vom clasifica vârstele în grupuri: 13 – 17, 18 – 24, 25 – 34, 35 – 44, 45 – 65+, 65. De asemenea, voi adăuga ID-uri în fișier. Deoarece fiecare rând este o persoană, voi folosi doar numere de rând.

PF16 <- PF16 %>%
  filter(age <= 102) %>%
  mutate(ID = row_number(),
         age_group = cut(age,
                         breaks = c(12, 17, 24, 34, 44, 64, Inf),
                         labels = c("13 to 17", "18 to 24", "25 to 34", "35 to 44", "45 to 64", "65+"),
                         right = TRUE))

Pentru a crea variabila de grupare de vârstă, am folosit funcția de tăiere, unde îmi definesc punctele de pauză și folosesc dreapta = ADEVĂRAT pentru a spune că valoarea furnizată este sfârșitul fiecărei pauze. Prima valoare din notația „dreapta = TRUE” ar trebui să fie valoarea inițială minus 1. Să înlocuim și valorile lipsă (codificate în prezent cu 0) cu NA. Deoarece toate articolele noastre sunt într-un rând, putem folosi mutate(across(firstvariable:lastvariable)) în șirul pe care vrem să îl recodăm.

PF16 <- PF16 %>%
  mutate(across(A1:P10, ~na_if(., 0)))

Acum vrem să începem să identificăm oameni cu modele de răspuns care nu vor oferi informații semnificative. Aceasta ar include persoanele care au răspuns neglijent – cum ar fi selectarea aceleiași opțiuni pentru fiecare articol sau trecerea între două opțiuni (cum ar fi 4-5-4-5) – sau cu prea multe date lipsă. Cu toate acestea, vrem să fim conservatori în ceea ce privește cine eliminăm. Probabil, acesta a fost un sondaj voluntar pe care oamenii l-au făcut din interes sau curiozitate. În aceste cazuri, unele răspunsuri neglijente pot însemna că elementul a fost confuz, nu măsoară ceea ce ar trebui să aibă, etc. Dar asta nu înseamnă că ar putea să nu existe niște respondenți ai publicului captiv – persoane cărora li sa cerut să finalizeze măsura ca parte a cursului sau a unei activități de grup – care au vrut doar să termine. Fără să putem măsura sau controla contextul, pur și simplu nu știm. Acesta este motivul pentru care mi-ar plăcea să fiu conservator în ceea ce privește cine elimin, pentru că aș prefera să păstrez oamenii care au fost cu adevărat neglijenți decât să risc să îndepărtez oamenii ale căror răspunsuri „nepăsătoare” se datorează de fapt elementelor sau scalelor problematice. Există câteva moduri prin care putem măsura răspunsurile neglijente. Una este să se uite la cel mai lung șir al lor de răspunsuri identice. Cealaltă modalitate este cu variabilitatea răspunsului intra-individual, care este mai bună la detectarea persoanelor care se limitează la două opțiuni consecutive. Pachetul r, neglijent, poate face toate acestea pentru noi. Memento: dacă nu aveți un anumit pachet, va trebui să îl instalați mai întâi cu install.packages(„nume pachet”) înainte de a-l încărca. Funcția longstring va furniza numărul celui mai lung șir de răspunsuri repetate; adăugarea avg = TRUE ne va oferi, de asemenea, lungimea medie a șirurilor pe întregul rând. irv calculează variabilitatea răspunsului intra-individual sau cantitatea de variație a răspunsurilor fiecărui rând. Toate acestea vor fi mai ușor dacă avem un set de date care conține doar răspunsuri la item și generăm un nou set de date cu datele din funcțiile neglijente; în acest fel, nu vom folosi din neatenție date demografice, ID-uri sau rezultate dintr-o funcție anterioară. De asemenea, voi adăuga la setul meu de date de semnalizare numărul de răspunsuri lipsă și cel mai lung șir împărțit la numărul total de articole, pentru a măsura procentul de răspunsuri incluse în acel șir.

library(careless)

Items <- PF16 %>%
  select(A1:P10)

longstrings <- longstring(Items, avg = TRUE)

Flags <- tibble(
  ID = PF16$ID,
  longstring = longstrings$longstr,
  avgstring = longstrings$avgstr,
  irv = irv(Items, na.rm = TRUE),
  na_count = rowSums(is.na(Items)),
  pct_long = longstring/163
)

Să începem cu IRV, care ar trebui să ne ajute să identificăm cei mai grav infractori în ceea ce privește răspunsul neglijent. IRV-uri mai mici (să zicem, mai puțin de 0,50) ar identifica persoanele care au dat același răspuns sau unul dintre cele două răspunsuri la fiecare item. Să vizualizăm variabila noastră irv înainte de a lua orice decizie cu privire la ce să filtram.

library(ggthemes)
Flags %>% 
  ggplot(aes(irv)) + 
  geom_histogram() +
  theme_economist_white()
## `stat_bin()` using `bins = 30`. Pick better value `binwidth`.
## Warning: Removed 171 rows containing non-finite outside the scale range
## (`stat_bin()`).

Avem un număr de cazuri cu un IRV de 0. Acestea sunt adevăratele noastre linii drepte. Există, de asemenea, cazuri cu IRV de 0,50 sau mai puțin. Aceștia ar fi oamenii care sări între două opțiuni. Numărările generale sunt scăzute, așa că nu vom pierde prea multe cazuri prin filtrarea celor cu un IRV de 0,50 sau mai puțin.

Flags <- Flags %>%
  filter(irv > 0.50)

Acest lucru a scăzut 381 de cazuri. Acum să ne uităm la corzi lungi. Filtrul nostru IRV a scăpat de persoane care au arătat modele de răspuns neglijenți în întreaga măsură, dar probabil că avem încă răspunsuri neglijenți aici. Trebuie doar să fim judiciați și bazați pe date în modul în care îi identificăm.

range(Flags$pct_long)
## (1) 0.006134969 0.441717791

De asemenea, am rulat o histogramă de bază asemănătoare cu cea de mai sus pentru IRV (nu este ilustrată), iar numărul de peste 10% a fost atât de scăzut, încât nici măcar nu erau vizibili. Am reluat histograma, de data aceasta specificând lățimea binului pentru a afla o limită exactă și limitând scara la valori între 0 și 50% (din moment ce știm că cel mai lung șir al nostru este de 44%).

Flags %>%
  ggplot(aes(pct_long)) +
  geom_histogram(binwidth = .01) +
  scale_x_continuous(limits = c(0, 0.50)) +
  theme_economist_white()
  

Avem o scădere mare în jurul procentului de șir de 9%. Să vedem câte cazuri am pierde cu această limită, precum și 10%.

Flags %>%
  filter(pct_long >= 0.09)
## # A tibble: 335 × 6
##       ID longstring avgstring   irv na_count pct_long
##                        
##  1    42         15      1.90 0.553        0   0.0920
##  2    56         17      1.75 0.860        0   0.104 
##  3   176         15      1.96 0.769        1   0.0920
##  4   553         17      2.51 0.650        0   0.104 
##  5   617         17      2.51 0.737       11   0.104 
##  6  2038         17      3.40 0.688        0   0.104 
##  7  3418         18      2.09 1.31         0   0.110 
##  8  3995         15      1.47 1.30         1   0.0920
##  9  4035         15      2.86 0.985        0   0.0920
## 10  4385         16      2.12 0.849        0   0.0982
## # ℹ 325 more rows
Flags %>%
  filter(pct_long >= 0.10)
## # A tibble: 265 × 6
##       ID longstring avgstring   irv na_count pct_long
##                        
##  1    56         17      1.75 0.860        0    0.104
##  2   553         17      2.51 0.650        0    0.104
##  3   617         17      2.51 0.737       11    0.104
##  4  2038         17      3.40 0.688        0    0.104
##  5  3418         18      2.09 1.31         0    0.110
##  6  6013         19      1.68 0.805        0    0.117
##  7  6909         21      1.92 1.51         1    0.129
##  8  7120         17      2.76 0.574        2    0.104
##  9  7158         18      1.99 0.718        6    0.110
## 10  7686         18      2.04 0.706        0    0.110
## # ℹ 255 more rows

O limită de 9% se traduce într-un șir cel mai lung de 15, iar 10% se traduce cu 17. Majoritatea scalelor noastre conțin 10 itemi, cu excepția scalei B, intelect, la 13 itemi. În plus, fiecare scală conține 3-5 itemi formulați negativ. Dacă acele elemente și scale funcționează conform așteptărilor, cel mai lung șir posibil ar fi 8. Dar dacă acele elemente și scale nu sunt functioneaza conform asteptarilor? Ce se întâmplă dacă un element negativ, despre care dezvoltatorii testului credeau că reprezintă opusul trăsăturii măsurate, nu are nicio legătură?

În același timp, aceste grupuri reprezintă o mică parte din eșantionul total. Folosind o limită de 10%, am pierde doar aproximativ 0,5% din totalul nostru. Deci să folosim 10%.

Flags <- Flags %>%
  filter(pct_long < 0.1)
NAs <- Flags %>% 
  group_by(na_count) %>% 
  summarise(count = n())

head(NAs)
## # A tibble: 6 × 2
##   na_count count
##       
## 1        0 35127
## 2        1  8705
## 3        2  2595
## 4        3   903
## 5        4   423
## 6        5   158

Dacă am păstra doar cazuri complete, am mai avea peste 35.000 de cazuri cu care să lucrăm. Dar abordările noastre psihometrice (CTT și Rasch) pot gestiona unele (dar nu multe) date lipsă. Folosind o limită de 2 lipsă sau mai puțin, ne-ar permite să păstrăm cea mai mare parte a eșantionului nostru și nu ar trebui să ne afecteze capacitatea de a valida aceste scale.

Flags <- Flags %>%
  filter(na_count <= 2)

Acum că avem eșantionul nostru de oameni care par să fi depus un efort pentru a răspunde la elemente, putem filtra setul de date PF16 pentru a include doar acele persoane.

PF16 <- PF16 %>%
  filter(ID %in% Flags$ID)

Și pentru a-mi fi mai ușor, voi salva acest set de date, ca să pot începe cu el în următoarea mea postare, unde vom lucra la analiza psihometrice CTT!

write_csv(PF16, "Cleaned PF16 Data.csv")

Ne vedem în următoarea mea postare!

Dominic Botezariu
Dominic Botezariuhttps://www.noobz.ro/
Creator de site și redactor-șef.

Cele mai noi știri

Pe același subiect

LĂSAȚI UN MESAJ

Vă rugăm să introduceți comentariul dvs.!
Introduceți aici numele dvs.