오늘 제 목표는 R을 이용해
이런 데이터에서 compound(d1, d3)와 거기에 해당하는 gene을 추출해 DB화 하는 것입니다.
Class | compound | gene |
D1 | Palbociclib | CCND1 |
D1 | Palbociclib | CDK4 |
D3 | chelidonine_HL60 | CCL2 |
D3 | chelidonine_HL60 | CCL3 |
D3 | chelidonine_HL60 | TRIM14 |
... | ... | ... |
(완료시 테이블. (+)- 나 up down 같은 내용도 제거)
이 쪽이 재료 파일입니다.
그리고 전체 소스코드 입니다. 파일을 받으신 후 경로는 수정하는 것을 권해드립니다.
# Env setting
{
library(data.table)
library(stringr)
options(stringsAsFactors = FALSE)
options(digits = 10)
options(scipen = 100)
}
사용할 패키지들과 자주 사용하는 옵션입니다. library 부분만 필수라고 생각하시면 됩니다.
# Loading
{
DS = fread("c:/channy/DS.txt",header=FALSE)
# empty row exclude -> you can use na.omit()
DS = subset(DS,V1 != "")
}
사용할 파일을 불러옵니다. fread는 빠릅니다. 특히 ssd를 사용할 때 효과가 극대화 됩니다.
빈 칸이 있어서 제거도 해 주었습니다.
# get compound's location
main_names = grep(" : ", DS$V1)
# set main dataframe
temp_df = data.frame()
# variable for iteration
counter = 1
" : " 이 들어가 있는 줄이 compound가 있는 줄이므로, 이를 이용해서 DS 데이터프레임상의 위치를 추적합니다.
나중에 내용들을 합칠 빈 데이터프레임을 생성해 둡니다.
다음 컴파운드의 위치를 알아내기 위해 counter 변수를 만들어 둡니다.
( 어디부터 어디까지인지는 compound 위치 사이에 있는 것들이 gene이기 때문에, n번째 compound와 n+1번째 compound의 위치를 이용해 gene들을 구분했습니다.)
Compound 1
gene1
gene2
gene3
...
compound 2
gene4
...
# iteration for every compound
for (i in main_names){
네. 반복구문이 시작됩니다. 컴파운드들이 있는 번호 각각을 불러옵니다. 1, 4, 10번째 줄에 " : " 가 있으면, i가 1일 때, 4일 때, 10일 떄를 기준으로 반복문이 작동합니다.
# variables for sub iteration
start = i
if(counter != 27370){
end = main_names[counter+1]-1 # next compound's location - 1
}else{
end = length(DS$V1)
}
start(compound 위치)와 end(해당 컴파운드의 마지막 진 위치)를 정하는 부분입니다.
제가 사용한 방법은 n번째와 n+1번째 compound 위치사이의 gene을 리스팅 하는 방법인데, 마지막 compound는 다음 compound가 없습니다. 고로 예외 처리를 해서, 마지막인 경우는 다음 순서를 생각하지 않고 끝까지 가는 것으로 해 두었습니다.
temp_compound_name = strsplit(DS$V1[i]," : ")[[1]][2] # split by " : ". and pick second value
class_d = strsplit(DS$V1[i]," : ")[[1]][1]
class_d = str_extract(pattern = "(?<=\\().*?(?=\\))",class_d) # get sub_database's name. (d1, d3)
1. DS$V1[i] 는 i번째 comound가 있는 줄 내용입니다.
해당 줄을 " : " 를 기준으로 자르면 {Compound(D1) , compound명}으로 나뉩니다. 함수 리턴값이 조금 특이해서 [[1]][2]라고 해야 저 둘 중 뒷 값을 뽑아낼 수 있습니다.
정리하자면, temp_compound_name은 현재 for문 내에 있는 compound 이름이 들어갑니다.
2. Compound(D1) 부분에서는 D1 부분을 뽑아내야 합니다. 그래서 일단 Compound(D1) 전체를 가져왔습니다.
3. str_extract는 특정한 패턴의 문자열을 뽑아냅니다. class_d 의 내용은 "Compound(D1)"이고,
(?<=\\().*?(?=\\))
이 요상한 부분은 정규표현식 이라는 것입니다. 문자열을 (상대적으로) 쉽고 빠르게 다룰 수 있는 방법이죠.
(?<=\\() 부분에서 (?<= A )는 뽑아내려는 내용 앞에 A 가 있는 걸 찾아라. 라는 뜻입니다.
(?=\\)) 부분은 뒤에 "\\)"가 있는 걸 찾으라는 뜻이죠. 앞에 \\가 붙는 것은 문법상 R이 헷갈리지 않기 위해 표시를 해준 것입니다.
.*? 에서 "."은 줄바꿈을 제외한 아무거나, "*"은 몇 번이 반복되어도 된다(0포함), "?"는 가능한 적은 글자를 찾으라는 뜻입니다.
(아)이)스) 에서 같은 일을 실행할 때, "?"가 없이 실행하면 "아)이)스" 를 출력합니다. ?가 있으면 처음 만난")"에서 끝내서 "아"만 출력합니다.
# dataframe for each compound
temp_line = data.frame()
# each compound's iteration
# I reccomend to use 'papply'
for (j in seq(start+1,end)){ # +1 means extract compound name.
temp_line 에는 개별 compound에 대한 각 gene들이 리스팅 됩니다.
j는 start+1(컴파운드 다음 줄, 첫 gene), 부터 end(다음 컴파운드 직전 gene/혹은 마지막 gene)까지 각각 들어갑니다.
참고로 R 사용에 익숙하신 분이라면 papply 함수를 이용하시는 것을 권해드립니다. 멀티스레딩을 통해 속도가 향상될 수 있습니다.
# add compound name & gene ... to temp_line
temp_line = rbind(temp_line,c(class_d,temp_compound_name,DS$V1[j]))
colnames(temp_line) = c("class","compound","gene") # prevent error
}
temp_line에 하나의 compound에 속한 gene들을 전부 리스팅 합니다.
열이름을 정해주는 것은 rbind를 할 시 열 이름이 다르면 오류가 나면서 정상적으로 합쳐지지 않기 때문에 매 번 지정해 줍니다.
# add each compound's gene name ... to temp_df
temp_df = rbind(temp_df,temp_line)
#print(temp_compound_name)
print(paste0("progress... ", counter , " / ", length(main_names), " = " , counter/length(main_names)*100 , "%"
temp_df는 각 컴파운드별로 정리된 gene들 리스트를 다시 한 번 모아서 합칩니다.
print되는 부분은 실행하고 진행이 얼마나 되는지 중간중간 확인하기 위한 코드입니다.
))
counter = counter + 1 # next variable
}
}
반복을 끝내고, counter를 1 증가시켜서 다음 compound를 타겟으로 삼을 수 있게 해 줍니다.
# After shave
{
final_table <- temp_df
# upper character
final_table$compound <- toupper(final_table$compound)
# replace _down & _UP & (+)-
final_table$compound <- gsub("_DOWN","",final_table$compound)
final_table$compound <- gsub("_UP","",final_table$compound)
final_table$compound <- gsub("(+)-","",final_table$compound)
# get my data
real_final_talbe = subset(final_table, class == "D1" | class == "D3")
}
테이블이 정리되고 난 뒤, 추가요청이 있어 내용을 추가했습니다.
toupper는 대문자로 바꾸는 역할입니다. compound를 대문자로 바꾸었습니다.
gsub는 gsub(A,B,C)일 떄,
C에서 A를 찾아서 B로 바꾸는 함수입니다. _UP과 _DOWN 그리고 (+)- 같은 필요없는 내용은 다 제거했습니다.
subset을 이용해 D1과 D3만 걸러냈습니다.
'반치용 > 문제해결(trouble shooting)' 카테고리의 다른 글
파이토치/토치비전 설치 관련 (2) | 2020.03.07 |
---|---|
2020-02-29 기준 tensorflow 2를 위한 환경 세팅(2.1.0) (0) | 2020.02.29 |
[R]R에서 여러 환경 사용시 상대경로 활용법(서버, 데스크탑, 노트북, 협동 프로젝트) (0) | 2020.01.10 |
[R] R을 이용한 상대위험도 구하기 (relative risk,risk ratio) with epitab in r (0) | 2020.01.06 |
gpg 오류 대처 (0) | 2019.12.10 |
댓글