분류 전체보기

01.14 R세미나 2번째 시간

2019. 1. 14. 13:57

오늘은 Preprocessing 과 MicroArray된 데이터를 T -test와  SAM 분석하는 코드를 배웠는데,

전문지식들이 들어가서 어려웠다.


일기를 안쓰는 동안, SQL 세미나가 있었는데, 복습을 열심히 해야할 듯하다

PostgreSQL을 배워야, 사수선생님께 CDM를 다루는 연습을 할 수 있을 것 같아서

NGS 분석 세미나는 참석안할 것을 고려하고 있다.

리눅스 세미나까지만 해봐야겠다.


하하하 input되는 정보가 너무 많다 -ㅁ-;;

Python 정리 -> R 정리 -> SQL 정리 -> 머신러닝 정리 -> PostgreSQL 공부 및 정리 -> SQL 및 자연어처리 공부..


크허허허;

제일 하고 싶었던 파이썬으로 의료데이터 연습하기 세미나가 있었다.

R과 python세미나는 전부 연구실 선생님들께서 실습해주셨다.

하하하.

재밌다 진짜 하고 싶었던 것을 다 해보니.. 복습을 열심히해야지.

분석라이브러리를 사용하기보다는 정규표현식을 이용해서 일부 데이터를 추출하는 연습 위주로 했다.


오늘은 DB세미나를 듣는데,,, 음,,,

이것 역시 하고 싶었는데 잘 따라가야쥐..


image

'한의대 생활 > 본4 - SNUBI 인턴생활' 카테고리의 다른 글

01. 23 작성중이던 논문 통계 정리  (0) 2019.01.23
01.14 R세미나 2번째 시간  (0) 2019.01.14
01. 07 R 세미나1  (0) 2019.01.07
01. 06 교수님과 식사  (0) 2019.01.06
01. 05 출근 둘쨋날  (0) 2019.01.06

#### 실업률 그래프 분석 ####
# http://kosis.kr/index/index.do 
# 국내통계 > 주제별통계 > 고용임금 > 경제활동 인구조사 > 실업률 > 성/연령별 실업률
# csv로 저장후 unemployment_rate.csv

# 1. 데이터 준비
raw_df <- read.csv("data/unemployment_rate.csv", header = T, fileEncoding = 'CP949')
head(raw_df, 20)
summary(raw_df)
image
image

# 2. reshape2(melt)을 통해 좌우로 넓은 데이터 --> long한 통합 데이터 형태로 수정하기
http://nittaku.tistory.com/349

library(tidyr)
library(reshape2)
library(ggplot2)

#    id.var = c("")옵션을 통해 남아있을 칼럼들을 지정해주자.
#    녹는 칼럼은 칼럼명집합칼럼 : variable /  값 집합칼럼 : value로 생성된다.
df_m <- melt(raw_df, id.var = c("성별", "연령계층별"))
head(df_m)
image


# 3. 데이터 클리닝 - substr() -> paste()
# - 지저분한(R에서 자동생성한)하게 녹아있는 칼럼명수정해줘야한다.
# - 1) 년/월이 모여있는 variable칼럼에서 년/월의 숫자만 따로 추출하여 year칼럼 /month칼럼을 생성
# - 2) 따로 추출한 year와 month를 원하는 형태(yyyy-mm)로 합해주는 year_month 칼럼을 만들어 Date타입으로 형변환시킬 준비를 하자.
df_m$year = substr(df_m$variable, 2, 5)
df_m$month = substr(df_m$variable, 8, 9)
head(df_m)

df_m$year_month =paste(df_m$year, df_m$month, sep="-")
head(df_m)
image

# - 3) year_month 칼럼의 값을 as.Date()타입으로 바꿔주자.
# -    하지만, Data()타입으로 변환하기 위해선 -dd(일)의 형태가 반드시 필요하다.
# -    그래서 임의로 -01 을 만들어서 yyyy-mm-dd 형태를 만들어주자.
df_m$year_month = as.Date(paste(df_m$year_month, "01", sep="-"))
head(df_m)
str(df_m)
image
image

# 4) 필요한 칼럼만 챙기자.
df_select = df_m[, c("성별", "연령계층별", "year_month", "value")]
head(df_select)
summary(df_select)

# 5) NA가 있다면,, 제거하자.*** 행인덱싱 자리에 complete.cases( )***
df_cleaned = df_select[ complete.cases(df_select), ]
summary(df_cleaned)
image


# 칼럼명을 영어로.. 임시로 바꾸자.. 반드시x
colnames(df_cleaned) = c("sex", "age_group", "year_month", "value")
head(df_cleaned)


# factor범주형 데이터( sex, age_group)는 summary()에 나타난 순서가 levels이다.(수치형이라면 통계값이 있을 것임)
# levels순으로 범주형 데이터 값들도 levels(칼럼인덱싱) [인덱싱]으로  영어로 바꿔주자.

str(df_cleaned)
levels(df_cleaned$sex)
levels(df_cleaned$sex)[1] = "Total"
levels(df_cleaned$sex)[2] = "Male"
levels(df_cleaned$sex)[3] = "Female"

# age_group은 범주가 너무 많다. levels()로 대입하지말고, gsub()를 이용해 문자열 값을 대체하자.
# 1) 범주가 너무 많을 때는, gsub("발견할문자", "바뀔문자", 칼럼명)을 이용해 일단 간단하게 만들자
#    즉, 문자열 안에 "세" 나 "이상" 등을 지운 새로운칼럼을 하나 생성하자.

levels(df_cleaned$age_group)
df_cleaned$new_age_group <- gsub("세|이상", "", df_cleaned$age_group)
df_cleaned$new_age_group
df_cleaned$new_age_group <- gsub("계", "Total", df_cleaned$new_age_group)


head(df_cleaned)

df_final <- df_cleaned[, c("sex", "new_age_group", "year_month", "value")]
head(df_final)


# ggplot으로 그래프 그리기
- aes()에는 x축의 칼럼, y축의 칼럼 이외에 ~별로 나눌 그룹과, 색을 표시할 그룹을 지정할 수 있다.

ggplot(df_final, aes(x=year_month, y=value, group = sex, colour= sex)) + geom_point() + geom_line()# x축 칼럼, y축칼럼, ~별 그룹, 색으로 지정할 그룹
image

image

       
# 그래프를 못알아 먹겠으니 인덱싱을 통해 df를 연령대 잘라서 각각 그리기
df_20s <- df_final[which(df_final$new_age_group == "20 - 29"), ]
df_30s <- df_final[which(df_final$new_age_group == "30 - 39"), ]
df_40s <- df_final[which(df_final$new_age_group == "40 - 49"), ]
df_50s <- df_final[which(df_final$new_age_group == "50 - 59"), ]

ggplot(df_20s, aes(x=year_month, y=value, group = sex, colour= sex)) + geom_point() + geom_line()# x축 칼럼, y축칼럼, ~별 그룹, 색으로 지정할 그룹
image


# function으로 만들어서 연령대별로 넣기
# data.frame과 title을 받아서 그리기
plotF <- function(df, title){
   ggplot(df, aes(x=year_month, y=value, group = sex, colour= sex)) + geom_point() + geom_line() + ggtitle(title)
}

plotF(df_20s, "20대 실업률")
plotF(df_30s, "30대 실업률")
plotF(df_40s, "40대 실업률")
plotF(df_50s, "50대 실업률")

image

  • 의료 빅데이터의 종류
    • 전자의무기록
    • 환자질병 등록 정보
    • 환자 건강 모니터링 기기 자료
    • 유전체 정보
    • 보험청구자료


  • 의료기관의 정보시스템의 예
    • 전자의무기록(Electronic Medical Records : EMR) : 환자의 진료정보 전산화
    • 처방전달시스템(Order Communication System : OCS) : 각종 검사 및 약물 처방 정보 처리
    • 의료영상시스템(Picture Archiving and Communication System : PACS) : CT나 MRI 등 의료영상
    • 검사정보시스템(Laboratory Information Management System: LIMS) : 혈액검사 등 각종 검사정보 처리



  • 병원정보시스템
    • 운영계 : 실제 진료가 이루어지는 환자 정보들을 축적하는 단계
    • 분석계 : 축적된 자료를 활용하여 병원에서 사용자 중심의 의사결졍지원 및 다차원적 분석을 위한 정보 기반을 제공
      -> 표준화를 통해 여러 병원과 연결되어 환자 질병의 사전 예방 및 관리 중심으로 진화 중
      image


  • 현재의 병원정보시스템은 각 병원마다 다른 구조 -> 자기 병원의 환자 데이터를 기반한 연구만 가능
    각 병원의 데이터를 같은 포맷인 공통 데이터 모델(Common Data Model : CDM)로 변경하는 개념이 대두되고 있음.
    이러한 표준화된 데이터를 기반으로 최근 다양한 분산연구망(Distributed Research Network : DRN)을 통한 연구가 활발히 진행 중


  • DRN(Disributed Research Network)의 종류
    • Sentinel Initiatives
    • Observational Health Data Sciences  and Informatics(OHDSI)
    • National Patient Centered Clinical Research Network(PCORnet)


공통 데이터 모델

  • 개념 : 병원들의 데이터를 효율적으로 활용하기 위해 정의한 표준화 데이터 구조. 국제 표준용어체계 기반으로 구성되어 각 의료기관의 데이터를 공통 데이터 모델로 바꾸기 위해서는 각 의료기관에서 사용되는 용어들을 표준용어체계로 매핑하는 작업이 필요

  • 연구목적에 따른 종류
    - CDM의 구성항목은 각 모델의 목적에 따라 다르며, 의료기관이목적에 따라 선택하여 구축
    • Sentinel CDM(약물 감시 목적)
    • OMOP(Observational Medical Outcomes Partnership)
    • CDM(임상 연구 방법론의 적용 및 평가)
    • PCORnet CDM(환자중심 임상 연구 네트워크)
      image


  1. 약물 감시 : Sentinel CDM
    • 미국 FDA는 2008년 Sentinel Initiative(분산 연구망 일종) 를 통해 EMR과 보험청구기록 등 기존 데이터 베이스를 Sentinel CDM으로 변환
    • 분산형 정보체계 : FDA질의 전송 -> 각 기관은 정보보호기준에 따라 요약정보를 FDA에 전송하는 안전한 체계
    • 구성
      - 필수 테이블 : 등록(enrollment) , 인구통계(demographics), 외래 처방(outpatient dispensing), 방문기록(encounter), 진단(diagnosis), 처치/수술(procedure) 등 6 개
      - 부가적인 테이블 : 검사 결과(laboratory), 활력징후(vitals), 원내처방(inpatient dispensing), 원내수혈(inpatient transfusion), 사망(death), 그리고 사망원인(cause of death) 등 6개

    • 필수테이블은 모든 트너가 공통적으로 구축, 부가적인 테이블은 보험회사를 제외한 일부 의료기관에서만 CDM으로 구축
    • Sentinel CDM v7.0.0 구성요소
      - 18개의 연구기관(Data partner)이 Sentinel CDM 연구에 참여 중
      - 데이터들(records)은 PatID(unique person identifier)라는 고유 식별자로 연결
      - 13개 테이블 -> 특징별 8개로 분류 :
      1. Enrollment
      2. Demographic
      3. Dispensing
      4. Encounter, Diagnosis, Procedure
      5. Death
      6. Laboratory Result
      7. Inpatient Pharmacy
      8. Inpatient Transfusion
        image



  2. 임상 연구 방법론의 적용 및 평가 : OMOP CDM
    • OMOP에서는 분산형 연구망(DRN) 구축을 목표로 OMOP CDM을 개발하여 오픈소스 툴을 개발
    • 2013년 OHDSI Research Network로 변경하여 데이터 표준화(Data standardization), 의료기기 안전감시(Medical Product Safety Surveillance), 비교 효과 연구(Comparative Effectiveness Research : CER) 등을 다루고 있다.

    • OHDSI는 임상 효과 연구를 위한 보건의료 관찰자료(Observational data)의 효과적 활용을 위한 공공-민간 협력기구로서, 관찰 자료 분석 방법론 연구, 관찰 자료 처리용 분석도구 개발, 협력 연구를 위한 오픈소스 연구자원 구축을 목표로 함.

    • OMOP CDM v6.0은 총 40개 테이블로 구성, 크게는 7개의 엘리먼트로 구성
      1. Standardized Vocabularies
      2. Standardized Metadata
      3. Standardized Clinical Data Tables
      4. Standardized Health System Data Tables
      5. Standardized Health Economics Data Tables
      6. Standardized derived Elements
      7. Results Schema
        image

    • OMOP CDM의 목적 : 관찰 자료의 표준화된 포맷을 제공, 분석 방법론(알고리즘)을 적용하기 쉬운 구조로 임상연구에 중요한 약물 복용과 그 조건의 기간(Drug era, Condition era)의 정의를 제공



  3. 환자 중심 임상 연구 네트워크 : PCORnet CDM
    • PCORnet은 Patient Centered Outcome Research Institute(PCORI)가 환자 의사결정을 비교한 비교 효과 연구를 효율적으로 수행하기 위해 설입한 분산 연구망으로 4개의 의료기관, 6개의 보험회사가 참여하고 있다.
    • 연구의 정확도와 효율성이 높아진 대규모 연구를 수행함으로써 미국의 보건의료 시스템을 지원하는 것이 목표
    • 미국 PCORI에 의해 운영
    • PCORnet CDM v4.1Mini-sentinel CDM을 기반으로 하고 총 17개의 테이블로 구성
    • 효율적인 관찰연구, 실험연구를 지원하는 네트워크인 The National Patient-Centered Clinical Research Network(CCRNs)를 구축함으로써 비교효과연구를 수행하기 위한 역량을 증진시키는 것을 목적으로 함
    • 신약 개발과 질병의 메커니즘 규명 등과 같은 기존 연구보다는 대규모 임상시험을 시행하기 어려운 문제에 대해 의사결정을 지원하기 위한 관찰 임상연구를 수행하고자 하며, 2014년 아스피린이 심장질환을 예방할 수 있는지 알아보기 위한 빅데이터 연구를 시작
      image




공통 데이터 모델의 활용

대표적인 연구활동으로는 미국 FDA의 능동적인 약물 감시를 위한 Sentinel Initiative, OHDSI Research Network의 분산 네트워크 기반 임상 빅데이터 연구가 있다.


  1. 미국 FDA의 능동적 약물감시를 위한 Sentinel Initiative
    image

    • 미국 FDA가 특정 약물의 안정성 이슈를 협업센터에 문의
    • 협업센터는 약물 안정성 이슈를 Sentinel CDM으로 분석 가능한 질의로 변환 후 데이터 파트너에게 전송
    • 데이터파트너는 협업센터의 질의문에 따라 CDM으로 변환되어 있는 DB를 분석후 축약하여 요약결과를 다시 협업센터로 전송
    • 협업센터는 특정 약물 안정성 이슈의 분석 결과를 FDA에 전송



  2. OHDSI Research Network의 분산 네트워크 기반 임상 빅데이터 연구
    • 분산 네트워크를 활용한 CDM 임상 빅데이터 연구는 상이한 자체 DB를 가진 의료기관들이 정보를 공유하고 연구를 수행하는데 효과적이다.
    • 다양한 CDM 중 OMOP CDM은 Setinel CDM보다 연구목적의 복잡한 자료구조를 가지며, 다양한 표준용어체계의 매핑을 통해 구성된다.
    • OMOP CDM의 사용을 위해서는 SNOMED-CT, RxNORM, LOINC 등의 의료 국제표준용어'OMOP concept_id' 용어체계와 매핑해야하며, 이에 필요한 vocaabulary set을 concept 테이블에 담아 공개하고 있다.
    • OHDSI Research Network에서 제공하는 AchillesCDM 자료를 테이블별로 시각화해서 보여주며, Atlas웹 기반 자료분석 도구로 웹 인터페이스로 코호트 구축, 성향변수맞춤, 생존분석, 상대위험도 계산 등의 통계분석을 쉽게 할 수 있다.
      - 콜롬비아대학교에서는 류마티스 관절염에 대해 RWD를 기반으로 무작위 임상 시험 결과를 예측하는 연구 진행 중
      - 류마티스 관절염 환자에서 tocafitinib과 adalimumab 및 etanercept의 안정성을 후향적, 관찰적, 비교 코호트 연구를 진행하였다.
    • 결과적으로 OHDSI의 방향성은 아래 그림과 같다.
      image


#### F(피셔) test ####
# rbook p354 : 2개의 데이터의 분산-퍼진정도를 비교한다
# 세미나에서는 two sample t-test전에 f - test로 등분산/이분산을 구분해서 계산해야한다고 하였다.


f.test.data <- read.table('data/f.test.data.txt', header = T)
f.test.data

# 1. 각 데이터(칼럼별)의 분산 알아보기
var(f.test.data$gardenB) # 1.3
var(f.test.data$gardenC) # 14.2

#### 2. f-test를 통해 통계학적으로 유믜미적으로 분산의 차이가 있는지 보기***####

# 1) 분산이 큰 값을 분자***로 하여 ***분산비율.ratio 구하기
attach(f.test.data)
F.ratio = var(gardenC) / var(gardenB) # 10.6

# 2) F.ratio의 그래프(F 분포의 확률밀도 함수)에서 하위 2.5% 이하거나 (~95%~) 상위 2.5%(97.5% 이상) = p-value(0.05이하) 에 속하면 유의미한 차이가있다!***
# 즉, pf(F.ratio, n, n) 의 값이  0.25 이하  or 0.975(0.25+0.95)이상일 경우, 분산차이는 유의미하다.
# H0 : 2개의 분산이 다르지 않다.
# 만약 하위2.5% 이하나 상위 2.5%이상에 속한다면( = p-value : 0.05이하), H0거절 H1(분산이 다르다)를 채택image

# 여기서 자유도에 따라 달라진다. 개수가 늘어나면 그래프 봉우리가 오른쪽으로 이동한다.
# 자유도 = 데이터개수 - 1


image
length(gardenB) # 10

# pf()로 F.ration를 이용하여 그래프상(F 분포의 확률밀도함수)의 넓이(density, %) 구하기
pf(F.ratio, 9, 9) # 0.9991879 -> 왼쪽부터 2.5 + 95 = 97.5보다 크니 상위25% 이상으로 분산차이가 유의미하다.


# 참고) qf()로 pf값을(넓이, %)을 이용한  F.ratio기(F-test그래프의 x값) 구하기
qf(0.9991879, 9, 9) #10.66666 -> F.ratio = 그래프상의 x 구하기


# pf값은 그래프상의 왼쪽부터 넓이다. 전체넓이인 1에서 빼주면, 오른쪽 나머지 넓이 상위 몇퍼센트인지 알 수 있다.
# 이것에 2를 곱하면, 양쪽 넓이가 나올 것인데, 이것이 5% 0.05보다 작아야 유의미한것이다.
# p-value에 대해 계산하는 것

2 * ( 1- pf(F.ratio, 9, 9)) # 0.0016 < 0.05  ==> H0를 거절하고 분산이 서로 유의미하게 차이가 난다.

# **** 한번에 F-test하는 방법****
# F.ratio 값만 다르다. 왜냐하면 막.. 순서대로.. 앞에 것을 분자로 넣기 때문에..(원래는 큰값이 분자로)
# 그러나 p-value값으로 비교하는 것이 최종목적이라 상관은 없다고 한다.

var.test(gardenB, gardenC)
# F test to compare two variances

# data:  gardenB and gardenC
# F = 0.09375, num df = 9, denom df = 9, p-value = 0.001624
# alternative hypothesis: true ratio of variances is not equal to 1
# 95 percent confidence interval: 0.02328617 0.37743695
# sample estimates: ratio of variances  0.09375

### R-squared의 종류 ####
#점들이 퍼져있는 정도, 분산의정도
# multiple ->변수와 관계없는 R-squared / adjusted-> x값이 늘어날수록 수치가 줄어드는 R-suared
year <- c(2000:2004)
value <- c(2.3, 3.2, 5.6, 5.4, 5.8)

par(mfrow=c(1,1))
plot(year, value)

fit <- lm(value ~ year)
abline(fit, col="red")

summary(fit)# R-squared 0.82/0.76
image


# 좀 더 선형에 가깝게 3번째 값 조절 -> R-squared 값이 올라간다.
year <- c(2000:2004)
value <- c(2.3, 3.2, 4.6, 5.4, 5.8)

par(mfrow=c(1,1))
plot(year, value)

fit <- lm(value ~ year)
abline(fit, col="red")

summary(fit)# R-squared 0.96/0.95
image


#### 2. plot(fit - lm()결과 ) ####
# *** 원래는 기본plot() 위 에다가  abline( lm결과 )으로 넣어주면 lm선으로 나왔음.
# 그래프 4개를 return한다. -> 콘솔에서 enter쳐야함
plot(fit)
# 4개를 par(mfrow)를 이용해 한번에 subplots처럼 그리기
par(mfrow = c(2,2))
plot(fit)

# 1번째 그래프 : 잔차그래프 -> 0에가깝에 수렴할 수록 좋은데 왔다갔다함
# 2번째 그래프 : QQplot( 정규분포의 정도를 보는 )
# 3번째 그래프 : 잔차에 루트씌운 그래프
# 4번째 그래프 : outlier처럼 영향을 크게 주는 데이터를 확인할 수 있다. -> Cook's distance에 가깝거나 포함되는 outlier 데이터
image


# 선형모델로 설명된다고 하지만,, 왔다갔다 패턴을 가진 예1
par(mfrow = c(1,1))
x=c(1, 2, 3, 4, 5, 7, 8, 9, 10)
y=c(2, 1, 4, 3, 6, 5, 8, 7, 9)
plot(x, y) #올라갔다가 내려갔다가 하는 패턴이 있음. # 어떤 변수를 놓쳤다는 것을 의미할 수도.. 날씨-계절변수
fit <- lm(y~x)
abline(fit, col="red")

summary(fit) # 별표있고, R-squared 높고, p-value가 낮으나 잔차가 왔다갔다하므로 < 좋은 모델이라고 할 수 없을 것이다.. >
image

# *** plot(fit)
# 잔차가 왔다갔다한다 -> 좋은그래프가 아니다.
# 이런식으로 패턴이 있는 데이터 -> 좋은 모델이 아니다.
# 그러나 확인할 수 있는 것에는 괜찮으니 --> 놓친 변수를 차자.

par(mfrow = c(2,2))
plot(fit)
image



# 선형모델로 설명된다고 하지만,, 왔다갔다 패턴을 가진 예2
par(mfrow = c(1,1))
x=c(1, 2, 3, 4, 5, 7, 8, 9, 10)
y=c(2, 3, 4, 5, 0, 2, 3, 4, 5)
plot(x, y) #올라갔다가 내려갔다가 하는 패턴이 있음. # 어떤 변수를 놓쳤다는 것을 의미할 수도.. 날씨-계절변수
image
fit <- lm(y~x)
abline(fit, col="red")
image

summary(fit)
# 별표 x
# 점이 퍼진정도가 심하여 R-squared가 매우 작다.
# p-value가 매우커서 선형모델로 설명x

par(mfrow = c(2,2))
plot(fit)
# 잔차가 왔다갔다 한다.
# QQ는 괜찮아보이지만,, 잔차때문에.. 이 선형모델은 버려야한다.


# iris데이터에서 1종의 Species만 뽑아  length에 따른 width의  선형모델 알아보기
data(iris)
head(iris)

length = iris[which(iris$Species=="setosa"), ]$Sepal.Length
witdh = iris[which(iris$Species=="setosa"), ]$Sepal.Width
par(mfrow = c(1,1))
plot(length, witdh, col="blue")
image

# ***overlab된 데이터를 살짝 흔들고 싶을 땐 x변수에 jitter()
plot( jitter(length), witdh, col="blue")

# 선형모델 만들기
fit <- lm(witdh ~ length)
abline(fit, col="red")

image

#확인하기
summary(fit)
par(mfrow=c(2,2))
plot(fit) # 완벽한 1자는 아니더라도 잔차가 0에 가까운 선을 보인다.
# ***4번째 그래프를 보니 42번째 데이터가 영향을 많이 준다 = outlier일 것이다.

image


# ***boxplot()로 y값 그려 outlier확인해보기
#참고 : outlier확인 시각화 / http://nittaku.tistory.com/353
par(mfrow=c(1,1))
boxplot(witdh) # boxplot에는 y값만 넣기***! 하나만 티어나와있다..
image

# *** 아웃라이어 제거해보기
length_new = length[-42]
witdh_new = witdh[-42]
boxplot(witdh_new)
image

plot(jitter(length), witdh, col="blue")
# 비교
plot( jitter(length_new), witdh_new, col="blue")
image
# lm라인 추가해보기
fit2 <-lm(witdh_new ~ length_new)
abline(fit2, col="red")

# 기존lm라인을 노란색으로 추가해보기
abline(fit, col="yellow")

image

# fit결과 전체 그리기 *** 원래는 abline으로 넣어주면 선으로 나왔음.
par(mfrow=c(2,2))
plot(fit2) # cook's distance에 다가가는 점없어짐.
image


#### 선형회귀모델 최종 확인 ####
# 변수에 별표 / R-Square / p-value  확인
# plot(fit)으로 잔차의 패턴 확인
# 왔다갔다한다면 , 선형모델로 나오더라도 다른 변수 집어넣기

#### *** 변수 추가해보기 *** ####
x=c(1, 2, 3, 4, 5, 7, 8, 9, 10)
y=c(2, 1, 4, 3, 12, 5, 8, 7, 9)
z=c(2, 1, 4, 3, 12, 5, 8, 7, 10)
# lm(z ~ x + y) 형태로 넣기 나머지 2개는 +로 연결해줌. 더하기는 아님 ****
fit3 <- lm(z~ x+y)
summary(fit3)  # y변수에만 별표 3개이다. x는 버려도 될 듯

par(mfrow=c(2,2))
plot(fit3)

# 별표없는 x를 지우고 해보자..
fit3 <- lm(z~ y)
plot(fit3) # 9번째 잔차만 많이 티어나와있다.

01. 07 R 세미나1

2019. 1. 7. 21:50

나는 참 운이 좋은 것 같다..

R을 공부해야할 찰나에 의료정보 랩실에 인턴으로 오고

좋은 선생님들도 만났는데,,

우리 연구실 선생님들께서 실습세미나를 나가시는 정밀의료 전문인력 양성 ~ 의료데이터분석 전문가 기본과정 세미나에

나도 들을 수 있다니...ㅠㅠ

image

가려운 부분이 긁여지는 느낌이다..

열심히 복습해야지 하하하하하

'한의대 생활 > 본4 - SNUBI 인턴생활' 카테고리의 다른 글

01.14 R세미나 2번째 시간  (0) 2019.01.14
01. 09 ~ 11 Python 세미나 & DB 세미나  (0) 2019.01.11
01. 06 교수님과 식사  (0) 2019.01.06
01. 05 출근 둘쨋날  (0) 2019.01.06
01. 03 출근 첫날  (0) 2019.01.06

01. 06 교수님과 식사

2019. 1. 6. 02:41

인터넷으로만 보던 교수님과 점심약속이 잡혔다.

지금 우리들이 뭐하고 있는지 뭐하고 싶은지 물으셨고

프로그래밍 관련 얘기를 하다가

교수님의 과거 역사를 들었다.


... 교수님은 괴수시다...

프로그래밍의 바닥이라고 할 수 있는 assembly어부터 시작하셨고,,,

MIT 공대도 나오시고,,

통찰력이나 미래를 내다보시는 것이

그냥 다른사람 같았다..

흐흐흐...


컴퓨터 관련 얘기를 하다보니, 뻘쭘하지도 않고 재밌게 2시간이 순삭되었다.

고기도 실컷먹고, 기분좋은 하루였다.

01. 05 출근 둘쨋날

2019. 1. 6. 02:39

오늘은 다른그룹(이우*, 권호*, 유승*) 선생님 3분께서 점심을 함께 했다.

많은 정보를 노출하긴 싫지만, 안잃어버릴려고 이름과 특징을 기억해두려함.

한분은 시크해보이셨고

한분은 엄청~나게 친절하시고

한분은 능력자포스에 게임, 문화 등 내 관심분야를 모두 꾀고 계셨다.

이분께서 SNUBI 홈페이지 계정도 알려주셨다.


이분들은 탁구에 관심이 많으셔서, 같이 점심시간에 탁구를 쳤다

근 2년만에 탁구를 쳤는데, 몸이 풀리는데까지 한참 걸렸다.

image


다행히 또 선생님들과 공감대가 형성되어서 다행이다.


오늘은 CDM에 대한 자료와 약간의 임무를 부여받았다. 하하하

image

그리고 출입증도 얻었다!!

image

이를 위해, 과학기술인등록번호를 등록하였고, 연구원 등록신청서를 작성해서 비서선생님께 갖다드렸다.

01. 03 출근 첫날

2019. 1. 6. 02:33

교수님께서 같이 인턴으로 들어온 김병*선생님과 나를 불러 무엇이 하고 싶은지 물으셨다

그리고 하고싶은 연구경험에 적합한 선생님을 추천해주셨다.


인턴이 들어오더라도 보통은 방치(?)하는 경우도 많다고 들었는데,

1년차 선생님 등 4인조(안세*, 한*, 최*, 최정* 선생님)께서 점심식사를 사주시고 기본적인 설명을 해주셨다.

운이 좋게도 같은 한의사 출신 선생님께서 나의 관심분야에 대한  연구를 하고 계셨다.

말을 참 이쁘게 하신다.

연구에 방해 안되게 잘 해야할텐데..


같은 동료선생님은 다른 연구실로 갔다. 열정이 뛰어나신 것 같음. 대학원 진학을 희망하심.

인터넷

최소 2대의 컴퓨터가 필요하다.
image

  • Client : 요청하는 사용자(갑)
  • Server : 응답하는 서비스 제공자(을)
    - 만약 요청하는 분야가 Web이라면 Web client / Web server라고 할 수 있다.

MySQL을 설치하면, Server와 Client 2개를 모두 설치하는데, 아래와 같다.
image

  • database client : mysql -uroot -p 명령어 기반의 client인  MySQL monitor
    image
  • database server : 데이터가 저장되고 응답하는 쪽


MySQL Client - 2번째 database clinet WorkBench

  • MySQL monitor : 서버와 함께 설치됨. 명령어기반이라 어디서든(서버컴퓨터에서도) 제어가능
  • MySQL Workbench : Gui기반의 client, MySQL 공식제공 client

설치 : https://www.mysql.com/products/workbench/


  1. database server에 연결하기
    • 참고) MySQL monitor에서 -h   local host or 127.0.0.1은 생략된 것이다.
      c:\Bitnami\wampstack-7.1.25-0\mysql\bin>mysql -uroot -p -hlocalhost
      c:\Bitnami\wampstack-7.1.25-0\mysql\bin>mysql -uroot -p -h127.0.0.1

    • Workbench에서는 북마크 방식으로 서버를 추가할 수 있다. 홈화면에서 +를 누른뒤
      - 서버이름,
      - connection method : Standard TCP/IP 선택
      - hostname : -h에 해당하는 서버컴퓨터 주소 / port는 보통 3306
        * defaul 127.0.0.1 인데, localhost로 입력시 test connection할때 에러가 날 수 있다. ip로 변경하면 된다.
        * port 3306은 처음 APM7으로 설치시 할당되었고, bitnami로 2번째 설치시는 3307로 할당되었으니, 나의 경우 3307로 연결함.
      - username : 우리가 만들었던 username 기본 root
      - default schema : 비워두자.
      image
      image
      image


    • 연결이 완료되고 더블클릭해보면, MySQL monitor(명령어)로 작성했던 DATABASE명이 보일 것이다.
      image


  2. 데이터베이스 선택 및 query문 날려보기
    - 해당 db를 더블클릭하고, Query라는 스크립트에 작성후 [번개]표시를 누르면 작동된다.
    image
    image


  3. schema(db)생성해보기
    - 가장 첫번째 아이콘 클릭
    image

    - schema(db)이름 선택 및 Apply를 통해 쿼리문 확인
    image
    image

    - 생성확인하기
    image
    image



  4. table 만들기
    -  2번째 아이콘을 선택하면 된다.
    image
    image


    - 각종 내용을 채워준다.
    - TEXT()는 안되니 TEXT로 바꿔주자.
    image
    image
    image


    - 마우스를 데면 오른쪽끝에 작은 table이 뜨는데 클릭하면, table의 내용물을 볼 수 있다.
    image


    - 표를 클릭해서 데이터를 입력하면 되지만, NOW()는 입력안되는 것 같다. sql문을 보면 'NOW()'로 문자열로 입혀지기 때문인 것 같음.
    image
    image

image

2개의 독립된 테이블을 JOIN을 통해서 하나의 테이블 형태로 보는 방법에 대해 알아보자.

  1. 결합고리(joint)는 topic테이블의 author_id와 author테이블의 id이므로
    명령문은 'topic 테이블의 모든 데이터를 출력하는데, author_id의 값과 author테이블의 id값이 같은 것 author테이블의 값을 붙혀'이다.

    mysql> SELECT * FROM topic LEFT JOIN author ON topic.author_id = author.id;
    image

  2. 이제 author_id 칼럼과 id칼럼을 제외하고 특정칼럼들만 가져와서 안보이게 하자.
    - 2개의 테이블 모두 같은명의 id칼럼을 가지고 있으므로, ambiguous라는 에러가 뜬다.
  3. mysql> SELECT id, title, description, created, name, profile FROM topic LEFT JOIN author ON topic.author_id = author.id;
    ERROR 1052 (23000): Column 'id' in field list is ambiguous

    image
    이럴때는 칼럼명앞에 table명.칼럼명을 적어주면 된다.

    mysql> SELECT topic.id, title, description, created, name, profile FROM topic LEFT JOIN author ON topic.author_id = author.id;
    image

  4. topic 테이블의 id칼럼명을 다른 것으로 변경시켜 보여줄 수 도 있다.
    mysql> SELECT topic.id AS topic_id, title, description, created, name, profile FROM topic LEFT JOIN author ON topic.author_id = author.id;
    image

기존의 테이블에서 중복을 제거했다는 것은 매우 중요한 일이다. -> 하나만 바꿔주면 전체가 바뀐다.
image

image


topic테이블은 글에 대한 내용이라면, comment 테이블이 존재할 수 있다. 여기에서도 author와 profile이 필요할 것이다.
comment 테이블에 author_id칼럼을 만들고 역시 author 테이블에서 가져오면 될 것이다.
image

image

관계형 데이터베이스

image

위의 table에서 데이터가 중복되는 부분이 있다. -> 개선의 여지가 있다.
만약, 중복된 데이터의 수정이 필요한 상황이라면 현재의 상태에서는 모든 데이터를 수정해야할 것이다.

  1. 중복되는 데이터를 가진 author와 profile을 새로운 author라는 table을 새로 만들어보자.
    image

  2. 기존의 table에서 author와 profile을 빼고, author_id라는 칼럼으로 대체 + author table의 id값을 대체하자.
    image

  3. 이제 author테이블 값만 바꾸면 -> topic 테이블의 모든 author_id는 자동으로 변경된 내용이 관계될 것이다.
    유지보수가 훨씬 편해진다.
    image


중복을 제거하여 별도의 테이블을 만들고 참조값만 적어주면, 유지/보수의 장점이 생긴다.

하지만, 직관적이지 못한, 별도의 테이블도 열어봐야하는 단점도 생긴다.

그래서 필요한 것이  별도의 테이블로 중복을 방지하여, 유지보수를 편하게 + 볼때는, 하나의 table로 합쳐진 형태의 직관적으로 만들어야하는데, 이것을 관계형 데이터베이스이고 저장할때는 별도로 + 보여줄때는 합쳐서를 실현해보자.
image


기존 테이블 2개로 분리하기

  1. 기존의 테이블의 이름 바꿔서 백업하기
    RENAME TABLE topic TO topic_backup;
    image

  2. author+profile을 author_id로 참조하는 형태의 새로운 테이블 만들기
    mysql> CREATE TABLE topic(
         -> id INT(11) NOT NULL AUTO_INCREMENT,
         -> title VARCHAR(30) NOT NULL,
         -> description TEXT NULL,
         -> created DATETIME NOT NULL,
         -> author_id INT(11) NULL,
         -> PRIMARY KEY(id)
         -> );
    image

  3. author 테이블 새로 만들기
    mysql> CREATE TABLE author(
         -> id INT(11) NOT NULL AUTO_INCREMENT,
         -> name VARCHAR(20) NOT NULL,
         -> profile VARCHAR(200) NULL,
         -> PRIMARY KEY (id)
         -> );
    image

  4. author 테이블을 기존 백업한 테이블을 보며 데이터 입력하기
    INSERT INTO author ( ) VALUES( );
    - *id값은 칼럼괄호에 안넣으면 자동으로 1씩 증가하지만, 여기에선 직접 증가한다.
    mysql> INSERT INTO author (id, name, profile) VALUES(1, 'egoing', 'developer');
    image

  5. 새로운 topic 테이블에 author_id값을 입력하면서 새로 작성하자.
    mysql> INSERT INTO topic (id, title, description, created, author_id)
         -> VALUES(1, 'My SQL', 'MySQL is ...', '2018-02-09 17:49:59', 1);
    image

  6. 나머지 데이터도 이런식으로 입력하다가, 새로운 author가 등장하면
    1) author 테이블에서 추가 -> 2) topic테이블에서 author_id 입력을 해주자.

    mysql> INSERT INTO topic (id, title, description, created, author_id)
         -> VALUES(2, 'Oracle', 'Oracle is ...', '2019-01-04 10:48:24', 1);
  7. mysql> INSERT INTO author (id, name, profile) VALUES(2, 'duru', 'data administrator');

    mysql> INSERT INTO topic (id, title, description, created, author_id)
         -> VALUES(3, 'SQL server', 'SQL server is ...', '2019-01-04 10:49:23', 2);
    mysql> INSERT INTO author (id, name, profile) VALUES(3, 'taeho', 'data scientist, developer');


    mysql> INSERT INTO topic (id, title, description, created, author_id)
         -> VALUES(5, 'MongoDB', 'MongoDB is ...', '2019-01-04 10:52:30', 1);

    image

#### 부트스트래핑 ####
# ****쓰는 이유 : 많은 test들이 정규성을 가정하고 쓴다(student's t) 하지만,
부트스트레핑을 쓰면, 적은 데이터라도 정규분포를 형성시켜 --> 모집단의 평균을 추정한다.
# https://thebook.io/006723/ch10/08-2/
# 부트스트래핑은 주어진 데이터로부터 복원 표본을 구하는 작업을 여러 번 반복해 원하는 값을 추정한다. 한 가지 예로 평균의 신뢰 구간을 구하는 경우를 생각해보자. 평균의 신뢰 구간은 평균이 속할 범위를 95% 신뢰도로 찾는 것이다. 부트스트래핑은 데이터로부터 표본을 복원 추출로 구하고 이들의 평균을 기록하는 일을 반복한다. 이렇게 구한 평균들을 나열한 뒤 가장 작은 값으로부터 2.5%, 가장 큰 값으로부터 97.5% 지점의 평균 두 개를 구한다. 그러면 두 평균 사이의 구간이 평균의 95% 신뢰 구간이 된다.

# 지난시간 정규성이 없어보이던 데이터
light <- read.table("data/light.txt", header = T) # 하위폴더에 접근할때는 앞에 / 안붙히고 바로..
light

hist(light$speed, col = "green")
image

# QQplot으로 확인하는 정규분포
qqnorm(light$speed)
qqline(light$speed, col = "red")
shapiro.test(light$speed) # p-value = 0.09876 -> H0정규분포를 채택하긴 했으나 찜찜..
image


#### 부트스트래핑 ####
# 0) 데이터의 개수 알아놓기
length(light$speed) # 데이터 개수 : 20개


# 1) 몇번 쌤플링(추출)할 것인지를 --> 빈 숫자 데이터에 정해놓기
a <- numeric(10000) # 10000개의 빈 숫자데이터 생성 -> 샘플링할 횟수가 될 것임

# 2) 20개씩 복원추출(1개뺀뒤 넣고 다시뺌x20)한 sample의 분포를 히스토그램으로 한번 봐보기
hist( sample(light$speed, size=20, replace = T), col="green" )
hist( sample(light$speed, size=20, replace = T), col="red" )
hist( sample(light$speed, size=20, replace = T), col="blue" )
imageimageimage

# 3) 10000개의 빈공간에 < 각 sample들( - *20개를 - 복원추출(replace)한 것) 의 평균mean*** >을 집어넣음
  my) 데이터 20개짜리에 대해,  10000번을,  20개씩 복원추출하여 나온 각 평균을  for문을 통해서 집어넣는다.

# 20개를 복원추출한 샘플의 평균구해보기
mean(  sample(light$speed, size=20, replace = T))

for( i in 1:10000){
   a[i] <- mean(  sample(light$speed, size=20, replace = T)  )
}

# 4) 이제 10000개의 20개복원추출의평균  을  히스토그램으로 분포를 보자.
hist(a, col='yellow') # 정규분포를 띈다.

# 5) 10000개짜리 정규분포의 평균으로 -> 모집단의 평균(H0는 990일 것이다)를 추정하여 H0를 reject하거나 채택가능

# 6) 각 샘플들에서는 1000짜리도 등장하지만, 그것(20개-복원추출)의 평균한 것들은 최대값도 990(H0)에는 못간다.
#    결과적으로 빛의 속도 990이라는 H0는 reject할 수 있다.
#    자료가 충분하지 않을 때는, 부트스트래핑을 통해 데이터를 잔뜩 늘일고 + 정규분포를 만들어서-> 모집단의 평균을 추정한다.
#    중심값 극한 정리에 쓰인다?
#    1개의 샘플의 평균은 별 의미가 없으나 1000개 이상한 부트스트레핑의 평균은--> 모집단의 평균을 추정가능하다.
#  
max(a) # 978.5
mean(a) # 909.2256 --> 1. 윌콕슨검정 시간에 909은 H0를 채택했었는데, 그 값과 비슷

Update(수정)

image

  • UPDATE table명  SET 칼럼1=값1, 칼럼2=값2 WHERE id=로 필터링
    만약, WHERE 조건을 달지 않으면 , 모든 row가 그렇게 바뀐다.



image
image

  • 위 table에서 2번째 데이터에 내용을 수정해보자.
    UPDATE topic SET description = 'Oracle is ...', title = 'Oracle' WHERE id=2;
    image
    image



DELETE(삭제)

image

UPDATE와 마찬가지로, WHERE 조건을 달지 않으면 전체 데이터가 삭제되니 조심해야한다.


  • 5번째 데이터를 삭제해보자.
    DELETE FROM topic WHERE id = 5;
    image

+ Recent posts