R

t-test, anova-test

S0LL 2024. 10. 19. 12:04

## 가설 검증 

1. 당뇨인 군과 아닌 군의 평균체중은 차이가 있다.
2. 당뇨환자의 연령그룹이 40세 미만, 40~60, 60세 이상인 그룹 별 평균 체중은 차이가 있다.

## ex1.txt 
# 대상자 번호  pid
# 당뇨측정시점  redcap_event_name 
# 당화혈색소  HbA1c
# HbA1c(당화혈색소) ≥ 6.5% : 당뇨 정의

## ex2.txt 
# 체중_대상자 번호 BW_myhealth_id
# 체중_측정 일시 BW_date_measured
# 체중_측정값 BW_value

## ex3.txt 
# 대상자 번호 pid
# 대상자 나이 age 
# 대상자 성별 sex

 

 

1. 데이터 불러오기 및 전처리

# 데이터 불러오기 (txt 파일을 데이터프레임으로)
h_data <- read.table("ex1.txt", header = TRUE, sep = "\t")
bw_data <- read.table("ex2.txt", header = TRUE, sep = "\t")
age_data <- read.table("ex3.txt", header = TRUE, sep = "\t")

#불러온 데이터의 행 이름바꾸고싶을때 사용.
#현재는 pid로 행 이름을 통일해야 하므로 bw_data의 id부분을 pid로 바꾼다.
colnames(bw_data)[colnames(bw_data)=="BW_myhealth_id"]<-"pid"

# 필요한 열만 선택
h_data <- h_data[, c("pid", "hba1c")]
bw_data <- bw_data[, c("pid", "BW_value")]
age_data <- age_data[, c("pid", "age")]

#summary(bw_data)를 해보면 몸무게의 최대,최솟값이 너무 극적이라 범위 설정
bw_data<-bw_data[bw_data$BW_value>=30 & bw_data$BW_value<=150,]


#결측치를 제거하고 병합할지, 
#병합하고 결측치를 제거할지 판단.

#병합하고 결측치를 제거(추천)
------------------------------------
merged_data<-merge(merge(h_data,bw_data,by="pid"),age_data,by="pid")
merged_data<-merged_data[complete.cases(merged_data),]
------------------------------------

#결측치를 제거하고병합
------------------------------------
# NA 제거 및 중복 제거 (필요시)
h_data <- h_data[!is.na(h_data$hba1c), ]
bw_data <- bw_data[!is.na(bw_data$BW_value), ]
age_data <- age_data[!is.na(age_data$age), ]
merged_data <- merge(merge(h_data, bw_data, by = "pid"), age_data, by = "pid")
------------------------------------
#중복 pid가 많으므로 아래중하나를 이용해 중복제거
# 중복된 PID가 있는 행 제거
cleaned_data <- merged_data[!duplicated(merged_data$pid), ]
# 중복된 PID에 대해 BW_value와 hba1c 값을 평균으로 요약
cleaned_data <- aggregate(cbind(BW_value, hba1c) ~ pid + age, data = merged_data, FUN = mean)


# 당뇨 여부 변수 추가 (당화혈색소 6.5 이상일 경우 당뇨로 간주)
merged_data$diabetes<-ifelse(merged_data$hba1c>=6.5,"dang","nodang")

# 나이 그룹화 (40세 미만, 40~60세, 60세 이상)                             
merged_data$age_group<-cut(merged_data$age,breaks=c(0,40,60,Inf),labels=c("under40","40to60","over60"))

#case when
n$age_group <- case_when(
  n$age >= 30 & n$age < 40 ~ "30s",
  n$age >= 40 & n$age < 50 ~ "40s",
  n$age >= 50 & n$age < 60 ~ "50s"
)

 


2. 가설1 -> t-test과정

# 당뇨인과 비당뇨인 그룹별 정규성 검정
shapiro_test_diabetes <- shapiro.test(merged_data$BW_value[merged_data$diabetes == "dang"])
shapiro_test_non_diabetes <- shapiro.test(merged_data$BW_value[merged_data$diabetes == "nodang"])

# 결과 출력
shapiro_test_diabetes
shapiro_test_non_diabetes



//만약 데이터의 행이 5000개가 넘으면 shapiro 사용불가능.
//그럴때는 qqnorm을 통해 데이터가 대각을 많이 벗어나나 안벗어나나를 보고 정규성 판단.
> qqnorm(merged_data$BW_value[merged_data$diabetes=="dang"])
> qqnorm(merged_data$BW_value[merged_data$diabetes=="nodang"])


//등분산성이 성립하는지 확인하기 위한 분산분석
# 두 그룹 간의 분산 차이 확인 (당뇨와 비당뇨)
> var_test<-var.test(BW_value~diabetes, data=merged_data)
> var_test

//분산분석결과, p-value < 2.2e-16, 즉 0.05보다 작으므로 등분산성 성립 x

//따라서, t-test의 뒤에 var.equal=FALSE로 설정해둬야 한다.
# 등분산성을 가정하지 않는 Welch's t-test
> t_test_result<-t.test(BW_value~diabetes,data=merged_data,var.equal=FALSE)
> t_test_result

// t-test결과 p-value < 2.2e-16, 즉 0.05보다 작으므로 귀무가설을 기각한다.
// 또한 95%신뢰구간이 0을 포함하지 않으므로 두 그룹간 체중 차이가 유의미하다.

 


meansd, 더미테이블

> aggregate(BW_value~diabetes,data=merged_data,FUN=mean)
  diabetes BW_value
1     dang 69.03437
2   nodang 66.27956

> aggregate(BW_value~diabetes,data=merged_data,FUN=sd)
  diabetes  BW_value
1     dang 12.144990
2   nodang  8.016017

시각화

# 가설 1: 당뇨인과 비당뇨인 간의 체중 차이를 Boxplot으로 시각화
boxplot(BW_value ~ diabetes, data = merged_data, 
        main = "Boxplot of Body Weight by Diabetes Status",
        xlab = "Diabetes Status", ylab = "Body Weight (kg)", 
        col = c("lightblue", "lightpink"))

3.

가설2 -> ANOVA

# 당뇨 환자만 선택
> diabetes_data<-merged_data[merged_data$diabetes=="dang",]

#정규성검증예시
shapiro_under30_wt <- shapiro.test(sool_data$HE_wt[sool_data$age_group == "under30"])
shapiro_30to50_wt <- shapiro.test(sool_data$HE_wt[sool_data$age_group == "30to50"])
shapiro_over50_wt <- shapiro.test(sool_data$HE_wt[sool_data$age_group == "over50"])

# Bartlett's Test for homogeneity of variances (연령 그룹별 등분산성 검정)
> bartlett_test<-bartlett.test(BW_value~age_group,data=diabetes_data)
> bartlett_test


//등분산성 검증결과 p-value가 0.05이하이므로 성립하지 않는다. 따라서 oneway.test진행
# Welch's ANOVA (oneway.test 사용)
> welch_anova_result<-oneway.test(BW_value~age_group,data=diabetes_data,var.equal=FALSE)
> welch_anova_result


//만약 등분산성이 성립한다면
# 일반 ANOVA 수행
anova_result <- aov(BW_value ~ age_group, data = diabetes_data)
summary(anova_result)


#oneway.test결과 p-value < 2.2e-16이므로 연령그룹간 체중에 유의미한 차이가 있다.


#사후검정(oneway.test)
# 각 연령 그룹 간의 쌍별 t-test 수행 (Bonferroni correction 적용)
> pairwise_result<-pairwise.t.test(diabetes_data$BW_value,diabetes_data$age_group,p.adjust.method="bonferroni")
> pairwise_result


#사후검정(aov)
# Tukey 사후 검정 (일반 ANOVA에서만 사용 가능)
tukey_result <- TukeyHSD(anova_result)
print(tukey_result)
plot(tukey_result)

mean,sd, 더미테이블

> aggregate(BW_value~age_group,data=diabetes_data,FUN=mean)
  age_group BW_value
1   under40 64.01234
2    40to60 75.06238
3    over60 66.72361

> aggregate(BW_value~age_group,data=diabetes_data,FUN=sd)
  age_group  BW_value
1   under40  5.008812
2    40to60 15.073153
3    over60  9.910492

 


ANOVA결과 시각화

# 가설 2: 연령대별 당뇨 환자의 체중 차이를 Boxplot으로 시각화
boxplot(BW_value ~ age_group, data = diabetes_data, 
        main = "Boxplot of Body Weight by Age Group (Diabetic)",
        xlab = "Age Group", ylab = "Body Weight (kg)", 
        col = c("lightblue", "lightgreen", "lightpink"))