정보
-
업무명 : R을 이용한 자동으로 끄투 게임을 수행하는 프로그램
-
작성자 : 박진만
-
작성일 : 2021-01-22
-
설 명 :
-
수정이력 :
내용
[개요]
-
끄투라고 불리는 끝말잇기 웹 게임으로부터 사람들과 자동으로 게임을 수행하는 프로그램
[특징]
-
1대1 게임을 자동으로 수행
- 단어를 학습하여 사용하는 기능 추가
[기능]
-
데이터형 소개
[활용 자료]
-
없음
[자료 처리 방안 및 활용 분석 기법]
-
없음
[사용법]
-
소스 코드 예시 참조
[사용 OS]
-
Windows 10
[사용 언어]
-
R v4.0.3
소스 코드
[메인 프로그램]
-
라이브러리 및 웹 설정 로딩
- 단어사전 로딩 (게임 도중 지속적으로 업데이트 가능)
- 닉네임 및 INPUT tag의 아이디 지정
- selenium 패키지를 이용하여 접속
- 게임 수행 하는 서브 함수 로드
library(RSelenium)
library(rvest)
library(stringr)
library(tidyverse)
library(data.table)
library(foreach)
library(httr)
library(webdriver)
library(seleniumPipes)
library(readxl)
library(foreach)
library(ggwordcloud)
library(wordcloud2)
library(htmlwidgets)
library(webshot)
library(log4r)
library(readxl)
library(tcltk)
library(beepr)
library(noncompliance)
library(ggplot2)
Sys.setlocale("LC_ALL")
options(encoding = "UTF-8")
Sys.setenv(LANG = "en_US.UTF-8")
source("./sub2.R")
source("./sub.R")
## 크롬 드라이버 오브젝트 생성 ##
remDr = remoteDriver(
remoteServerAddr = "localhost"
, port = 5000L
, browserName = "chrome"
)
# 단어사전 path 지정
dataPath = "./word/input.csv"
## 단어사전 로딩 ##
wordDataL1 <- loadWordData(path = dataPath)
# 크롬 열고 사이트 접속
openChrome(remDr = remDr,site = "https://kkutu.co.kr/")
# 서버 접속
getUrl = "https://kkutu.co.kr/?server=0"
remDr$navigate(getUrl)
charID = "chatID를 입력해야 합니다"
myNick = "나의 닉네임을 입력해야 합니다"
############################# 게임진행 ############################
gameStart(nick = myNick,mod = "go",chatID = charID)
###################################################################
[서브함수]
- 서브 함수는 총 2개의 프로그램으로 나뉘어짐
- 하나는 게임의 진행 흐름을 판단하는 서브 함수이며, 나머지 하나는 게임의 실질적인 역할을 수행하는 서브 함수
gameStart = function(nick = nick,mod = mod,chatID = chatID, isAttack = ""){
chain_before = 0
nis = 0
# 게임 시작
while (T) {
nis = nis + 1
# 게임을 시작하는 조건을 충족시키면
if(nis == 1) {
wordLog = data.frame()
# 데이터를 로드하고
wordDataL1 = loadWordData(path = dataPath)
# 게임진행용 더미 워드 프레임 로드
gameData = wordDataL1
# 게임시작 및 라운드워드 획득
roundword = startGame_and_GetWord(remDr = remDr,mod = mod)
#roundword = startGame_and_GetWord(remDr = remDr,mod = "aa")
# 선후공 체크 #
isMyNameFirst = remDr$findElements(using="class name", value="game-user-name")
isMyNameFirstCheck = isMyNameFirst[[1]]$getElementText()
if(isAttack == "") {
if(isMyNameFirstCheck == nick) {
attackFlag = TRUE # 선공
wordEnd = roundword
# 사용할 단어 선택
selectWord = wordSelector(data = gameData,endword = wordEnd)
# 내가 쓸 단어가 있는 경우
if(nrow(selectWord) >= 1) {
word = selectWord$word
# 단어 메시지 보내기
sendChat(remDr = remDr,word = word,number = chatID,delay = 0.1)
# Sys.sleep(3)
# 단어 기록
wordLog = appendWordLog(wordLog = wordLog,word = word)
current_word = word
# 더미데이터에서 사용한 단어 삭제
gameData = gameData %>%
dplyr::filter(word != current_word)
}
} else {
current_word = ""
attackFlag = FALSE #후공
}
} else if (isAttack == TRUE) { # 내가 선공
attackFlag = TRUE # 선공
wordEnd = roundword
# 사용할 단어 선택
selectWord = wordSelector(data = gameData,endword = wordEnd)
# 내가 쓸 단어가 있는 경우
if(nrow(selectWord) >= 1) {
word = selectWord$word
# 단어 메시지 보내기
sendChat(remDr = remDr,word = word,number = chatID,delay = 0.1)
# Sys.sleep(3)
# 단어 기록
wordLog = appendWordLog(wordLog = wordLog,word = word)
current_word = word
# 더미데이터에서 사용한 단어 삭제
gameData = gameData %>%
dplyr::filter(word != current_word)
}
} else if (isAttack == FALSE) {
current_word = ""
attackFlag = FALSE #후공
} else {
print("error")
break
}
# 선후공 체크 #
}
############################ 게임 진행 중 단어 획득 ############################
## chain으로 단어 넘김 여부 확인 ##
chain = remDr$findElement("class name", "chain")
chain_before = as.numeric(chain$getElementText())
checkTime = checkTimeBar(remDr = remDr,delay = 0.1)
while(T) {
word = getGameWord(remDr = remDr,delay = 2,countEnd = checkTime*10)
# print(word)
# print(current_word)
if(word == current_word | word == ""){
next
}
if(word == "비정상 입력") {
next
} else {
chain = remDr$findElement("class name", "chain")
chain_after = as.numeric(chain$getElementText())
print("=========chain===========")
print(chain_before)
print(chain_after)
print("=========chain===========")
if( (word != "게임종료") & (chain_after==chain_before)) {
next
}
break
}
}
############################ 게임 진행 중 단어 획득 ############################
############################# 상대방의 미 입력으로 게임이 종료된 경우 ############
if(word == "게임종료") {
# 점수 계산
newdata = calcScore(data = wordDataL1,wordLog = wordLog)
# 계산된 단어 쓰기
fwrite(newdata,"./word/input.csv",sep=",",row.names = F)
# 단어사전 다시 로딩
# wordDataL1 <- loadWordData(path = dataPath)
break
}
############################# 상대방의 미 입력으로 게임이 종료된 경우 ############
# 단어 기록
wordLog = appendWordLog(wordLog = wordLog,word = word)
current_word = word
print(current_word)
# 더미데이터에서 사용한 단어 삭제
gameData = gameData %>%
dplyr::filter(word != current_word)
# 입력된 단어로부터 끝 단어 기록 #
wordEnd = str_sub(current_word,nchar(current_word),nchar(current_word))
# 단어가 두음법칙을 따르는 경우 끝 단어를 2개 지정해주는 부분
if(wordEnd == ")") {
wordEnd1 = str_sub(current_word,nchar(current_word)-1,nchar(current_word)-1)
wordEnd2 = str_sub(current_word,nchar(current_word)-3,nchar(current_word)-3)
wordEnd = c(wordEnd1,wordEnd2)
}
if(length(wordEnd) == 1){
wordEnd2 = duem(endword = wordEnd)
if(wordEnd2 != "") {
wordEnd = c(wordEnd,wordEnd2)
}
}
print(wordEnd)
# 단어 전송 무한루프
while (T) {
# 끝 단어로부터 내가 사용할 단어 선택
selectWord = wordSelector(data = gameData,endword = wordEnd)
# 내가 쓸 단어가 있는 경우
if(nrow(selectWord) >= 1) {
word = selectWord$word
print(word)
randomDelay = rnorm(n = 1,mean = nchar(word)/5,sd = 1)
if(mod == "pre"){
randomDelay = 0
}
print(randomDelay)
if(randomDelay <= 0.1) {
randomDelay = 0.1
}
## chain으로 단어 넘김 여부 확인 ##
chain = remDr$findElement("class name", "chain")
chain_before = as.numeric(chain$getElementText())
# 단어 전송
sendChat(remDr = remDr,word = word,number = chatID,delay = randomDelay)
endFlag = FALSE
current_word = word
endCount = max(nchar(current_word)*2,14)
checkWord = getGameWord(remDr = remDr,delay = 2,countEnd = endCount)
chain = remDr$findElement("class name", "chain")
chain_after = as.numeric(chain$getElementText())
## chain으로 단어 넘김 여부 확인 ##
print("=========chain===========")
print(chain_before)
print(chain_after)
print("=========chain===========")
# 나중에 기록된 시간이 더 크거나 같다 = 유효한 단어
if( chain_before != chain_after) {
# 단어 기록
wordLog = appendWordLog(wordLog = wordLog,word = word)
current_word = word
# 더미데이터에서 사용한 단어 삭제
gameData = gameData %>%
dplyr::filter(word != current_word)
endFlag = FALSE
# print(min(nchar(word) * 2,4))
# Sys.sleep(min(nchar(word) * 2,4) )
# 단어전송이 끝났으므로 무한루프에서 탈출
break
} else { # 그게 아니면 입력이 무효가 된 경우임
# 더미데이터에서 사용한 단어 삭제
gameData = gameData %>%
dplyr::filter(word != current_word)
# 본래 데이터에서 무효인 단어 삭제
wordDataL1 = wordDataL1 %>%
dplyr::filter(word != current_word)
# 단어 기록 없이 next로 넘어가기
endFlag = FALSE
next
}
} else if(nrow(selectWord) == 0 ) { # 내가 쓸 단어가 없는 경우
# 점수 계산
newdata = calcScore(data = wordDataL1,wordLog = wordLog)
# 계산된 단어 쓰기
fwrite(newdata,"./word/input.csv",sep=",",row.names = F)
# 단어사전 다시 로딩
# wordDataL1 <- loadWordData(path = dataPath)
endFlag = TRUE
break
}
}
if(endFlag == TRUE) {
break
}
}
############################ 게임 진행 ############################
return("gameEnd")
}
# cd selenium
# cd selenium
# java -Dwebdriver.gecko.driver="geckodriver.exe" -jar selenium-server-standalone-3.141.59.jar -port 5000
## 단어사전 로드하는 함수 ##
loadWordData <- function(path = path) {
## 단어사전 로딩 ##
wordData = fread(path,encoding = "UTF-8",header = T,sep=",")
wordData = wordData %>%
dplyr::mutate(startword = str_sub(word,1,1),
endword = str_sub(word,nchar(word),nchar(word)))
## 단어사전 로딩 ##
return(wordData)
}
setWindowTab = function (remDr, windowId) {
qpath = sprintf("%s/session/%s/window", remDr$serverURL, remDr$sessionInfo[["id"]])
remDr$queryRD(qpath, "POST", qdata = list(handle = windowId))
}
getXpathText = function(xpath) {
remDr$getPageSource()[[1]] %>%
read_html() %>%
rvest::html_nodes(xpath = xpath) %>%
rvest::html_text() %>%
str_replace_all(pattern = "\n", replacement = " ") %>%
str_replace_all(pattern = "[\\^]", replacement = " ") %>%
str_replace_all(pattern = "\"", replacement = " ") %>%
str_replace_all(pattern = "\\s+", replacement = " ") %>%
str_trim(side = "both")
}
getCssText = function(css) {
remDr$getPageSource()[[1]] %>%
read_html() %>%
rvest::html_nodes(css = css) %>%
rvest::html_text() %>%
str_replace_all(pattern = "\n", replacement = " ") %>%
str_replace_all(pattern = "[\\^]", replacement = " ") %>%
str_replace_all(pattern = "\"", replacement = " ") %>%
str_replace_all(pattern = "\\s+", replacement = " ") %>%
str_trim(side = "both")
}
## 크롬 오픈 후 원하는 사이트 접속하는 기능 ##
openChrome = function(remDr = remDr, site = site) {
# 크롬 열기
remDr$open()
getRootHandle = remDr$getWindowHandles()
getUrl = sprintf(site)
remDr$navigate(getUrl)
return("success")
}
getGameWord = function(remDr = remDr,delay = delay,countEnd = 300) {
## 상대방이 치는 단어를 획득 ##
checkCount = 0
while (T) {
errorFlag = FALSE
word = ""
checkCount = checkCount + 1
if(checkCount == 1) {
longwordDum = c()
longwordLen = c()
}
checkTime = checkTimeBar(remDr = remDr,delay = 0.1)
# 단어가 갱신되지 않는 경우 루프 종료
if(checkCount == countEnd | checkTime == 0.4) {
YYY = remDr$findElements("class name", "dialog-title")
if(YYY[[9]]$getElementText() == "게임 결과") {
remDr$findElement(using="id", value="result-ok")$clickElement()
Sys.sleep(delay)
remDr$findElement(using="id", value="result-ok")$clickElement()
nis = 0
return("게임종료")
} else {
nis = 0
remDr$findElement(using="id", value="result-ok")$clickElement()
Sys.sleep(delay)
remDr$findElement(using="id", value="result-ok")$clickElement()
return("게임종료")
}
}
XXX = tryCatch(remDr$findElements("class name", "display-text"),
error = function(e) print("NODEAL"),
warning = function(w) print("NODEAL"),
finally = NULL)
XXX2 = tryCatch(remDr$findElements("class name", "jjo-display"),
error = function(e) print("NODEAL"),
warning = function(w) print("NODEAL"),
finally = NULL)
longWord = gsub(x = XXX2[[1]]$getElementText(),pattern = "\n",replacement = "")
longwordDum = c(longwordDum,longWord)
longwordLen = c(longwordLen,nchar(longWord))
# 긴단어 GET
if(length(longwordLen) >= 2) {
if( ((longwordLen[length(longwordLen)-1] - longwordLen[length(longwordLen)]) <= -2) & countEnd == 300 ) {
return("비정상 입력")
}
if( (longwordLen[length(longwordLen)] >= 1 & longwordLen[length(longwordLen)] <= 4) & (longwordLen[length(longwordLen)-1]) >= 8 ){
# print(word)
word = longwordDum[length(longwordDum)-1]
if(grepl(x = word,pattern = "[A-Za-z]") == TRUE) {
return("비정상 입력")
} else if (grepl(x = word,pattern = ":")) {
return("비정상 입력")
}
return(word)
}
}
if(length(XXX) == 0) {
next
} else {
flagOfNull = FALSE
for (i in 1:length(XXX)) {
checkNull = tryCatch(XXX[[i]]$getElementText(),
error = function(e) print("NODEAL"),
warning = function(w) print("NODEAL"),
finally = NULL)
if(checkNull == "NODEAL"){
errorFlag = TRUE
break
}
if(checkNull == ""){
flagOfNull = TRUE
break
}
}
if(errorFlag == TRUE) {
next
}
if(flagOfNull == TRUE) {
next
}
for (i in 1:length(XXX)) {
# wordpart = XXX[[i]]$getElementText()
wordpart = tryCatch(XXX[[i]]$getElementText(),
error = function(e) print("NODEAL"),
warning = function(w) print("NODEAL"),
finally = NULL)
# print(wordpart)
if(wordpart == "" | wordpart == "NODEAL"){
errorFlag = TRUE
break
} else {
word = paste0(word,wordpart)
}
}
if(errorFlag == TRUE) {
next
}
return(word)
}
}
## 상대방이 치는 단어를 획득 ##
return(word)
}
startGame_and_GetWord = function(remDr = remDr,mod = "pre") {
if(mod == "pre") {
# 게임 시작 (연습)
remDr$findElement(using="id", value="PracticeBtn")$clickElement()
Sys.sleep(2)
remDr$findElement(using="id", value="practice-ok")$clickElement()
# 게임 시작 (연습)
} else if (mod == "go") {
# 게임 시작 (실제 게임)
remDr$findElement(using="id", value="StartBtn")$clickElement()
# 게임 시작 (실제 게임)
} else {
}
Sys.sleep(3)
## 라운드 시작 단어 획득 ##
round_current = remDr$findElements("class name", "rounds-current")
if(length(round_current) >= 1) {
# 선공 하는 경우 처리 해야 함
rountStart = round_current[[1]]$getElementText()
}
## 라운드 시작 단어 획득 ##
return(rountStart)
}
sendChat = function(remDr = remDr,word = word, number = number,delay = delay) {
timeLog = c()
while (T) {
timeis = checkTimeBar(remDr = remDr,delay = 0.08)
timeLog = c(timeLog,timeis)
len = length(timeLog)
# print(timeis)
if(len >= 2 & timeLog[len] != 999) {
if( (timeLog[len] - timeLog[len-1]) < 0 ) {
timeLog = c()
break
}
}
}
Sys.sleep(delay)
sendTextKey = remDr$findElements("id", paste0("UserMassage",number))
sendTextKey[[1]]$sendKeysToElement(list(word, "\uE007"))
# Sys.sleep(3.0)
return("success")
}
wordSelector = function(data = data, endwordFun = endword) {
# 끝 단어 기반 사용할 단어 선택 (점수에 따른) #
print(endwordFun)
if(length(endwordFun) == 1){
selectWord = data %>%
dplyr::filter(startword == endwordFun[1]) %>%
dplyr::arrange(desc(score)) %>%
dplyr::slice(1)
print(endwordFun[1])
print(data)
print(selectWord)
} else {
selectWord = data %>%
dplyr::filter(startword == endwordFun[1] | startword == endwordFun[2]) %>%
dplyr::arrange(desc(score)) %>%
dplyr::slice(1)
}
# 끝 단어 기반 사용할 단어 선택 (점수에 따른) #
return(selectWord)
}
wordSelector = function(data = data, endwordFun = endword) {
# 끝 단어 기반 사용할 단어 선택 (점수에 따른) #
print(endwordFun)
if(length(endwordFun) == 1){
selectWord = data %>%
dplyr::filter(startword == endwordFun[1]) %>%
dplyr::arrange(desc(score)) %>%
dplyr::slice(1)
print(endwordFun[1])
print(data)
print(selectWord)
} else {
selectWord = data %>%
dplyr::filter(startword == endwordFun[1] | startword == endwordFun[2]) %>%
dplyr::arrange(desc(score)) %>%
dplyr::slice(1)
}
# 끝 단어 기반 사용할 단어 선택 (점수에 따른) #
return(selectWord)
}
calcScore = function(data = data, wordLog = wordLog) {
##### 점수 계산 후 종료 - 리로딩 #######
wordLog <- wordLog %>%
dplyr::distinct() %>%
dplyr::mutate(score = 0) %>%
dplyr::mutate(startword = str_sub(word,1,1),
endword = str_sub(word,nchar(word),nchar(word))) %>%
dplyr::select(word,score,startword,endword)
tt = -1
cc = -1
for (i in nrow(wordLog):1) {
cc = cc + 1
tt = tt * -1
scoreRes = 1 / exp(cc)
print(scoreRes)
wordLog$score[i] = scoreRes*tt
}
wordDataNew = dplyr::full_join(data,wordLog,by=c("word"))
wordDataNew_L1 = wordDataNew %>%
dplyr::mutate(score.x = ifelse(!is.na(score.y),score.y,score.x)) %>%
dplyr::mutate(startword.x = ifelse(!is.na(startword.y),startword.y,startword.x)) %>%
dplyr::mutate(endword.x = ifelse(!is.na(endword.y),endword.y,endword.x)) %>%
dplyr::select(word,score.x,startword.x,endword.x)
colnames(wordDataNew_L1) = c("word","score","startword","endword")
for (dw in 1:nrow(wordLog)) {
for (dv in 1:nrow(wordDataNew_L1)) {
if(wordDataNew_L1$endword[dv] == wordLog$endword[dw]) {
#print(wordDataNew_L1$word[dv])
wordDataNew_L1$score[dv] = wordDataNew_L1$score[dv] + wordLog$score[dw]
#print(wordDataNew_L1$score[dv])
}
}
}
print(wordLog)
return(wordDataNew_L1)
}
appendWordLog = function(wordLog = wordLog, word = word){
wordLog = rbind(wordLog,word)
colnames(wordLog)[1] = "word"
return(wordLog)
}
checkTimeBar = function(remDr = remDr,delay = delay) {
Sys.sleep(delay)
timeBar = remDr$findElement(using="class name", value="jjo-turn-time")
timeBar = gsub(x = timeBar$getElementText(),pattern = "[가-힣]",replacement = "")
timeBarNum = as.numeric(timeBar)
if(is.na(timeBarNum)) {
return(999)
} else {
return(timeBarNum)
}
}
checkTotalTIME = function(remDr = remDr,delay = delay) {
Sys.sleep(delay)
timeBar = remDr$findElements(using="class name", value="graph-bar")
#print(timeBar[[6]]$getElementText())
timeBar = gsub(x = timeBar[[6]]$getElementText(),pattern = "[가-힣]",replacement = "")
timeBarNum = as.numeric(timeBar)
if(is.na(timeBarNum)) {
return(999)
} else {
return(timeBarNum)
}
}
duem = function(endword = endword) {
endword2 = ''
if(endword == '라') {
endword2 = '나'
} else if(endword == '락'){
endword2 = '낙'
} else if(endword == '릴'){
endword2 = '일'
} else if(endword == '를'){
endword2 = '늘'
} else if(endword == '랗'){
endword2 = '낳'
} else if(endword == '란'){
endword2 = '난'
} else if(endword == '랄'){
endword2 = '날'
} else if(endword == '릎'){
endword2 = '늪'
} else if(endword == '람'){
endword2 = '남'
} else if(endword == '랍'){
endword2 = '납'
} else if(endword == '랑'){
endword2 = '낭'
} else if(endword == '래'){
endword2 = '내'
} else if(endword == '랭'){
endword2 = '냉'
} else if(endword == '냑' | endword == '략'){
endword2 = '약'
} else if(endword == '량'){
endword2 = '양'
} else if(endword == '녀' | endword == '려'){
endword2 = '여'
} else if(endword == '녁' | endword == '력'){
endword2 = '역'
} else if(endword == '년' | endword == '련'){
endword2 = '연'
} else if(endword == '녈' | endword == '렬'){
endword2 = '열'
} else if(endword == '념' | endword == '렴'){
endword2 = '염'
} else if(endword == '녕' | endword == '령'){
endword2 = '영'
} else if(endword == '뇨' | endword == '료'){
endword2 = '요'
} else if(endword == '룡' | endword == '뇽'){
endword2 = '용'
} else if(endword == '뉴' | endword == '류'){
endword2 = '유'
} else if(endword == '뉵' | endword == '륙'){
endword2 = '육'
} else if(endword == '니' | endword == '리'){
endword2 = '이'
} else if(endword == '님' | endword == '림'){
endword2 = '임'
} else if(endword == '렵'){
endword2 = '엽'
} else if(endword == '례'){
endword2 = '예'
} else if(endword == '로'){
endword2 = '노'
} else if(endword == '록'){
endword2 = '녹'
} else if(endword == '롱'){
endword2 = '농'
} else if(endword == '뢰'){
endword2 = '뇌'
} else if(endword == '루'){
endword2 = '누'
} else if(endword == '륜'){
endword2 = '윤'
} else if(endword == '률'){
endword2 = '율'
} else if(endword == '륭'){
endword2 = '융'
} else if(endword == '륵'){
endword2 = '늑'
} else if(endword == '름'){
endword2 = '늠'
} else if(endword == '릉'){
endword2 = '능'
} else if(endword == '린'){
endword2 = '인'
} else if(endword == '림'){
endword2 = '임'
} else if(endword == '립'){
endword2 = '입'
} else if(endword == '릅'){
endword2 = '늡'
} else if(endword == '룹'){
endword2 = '눕'
} else if(endword == '랏'){
endword2 = '낫'
} else if(endword == '램'){
endword2 = '냄'
} else if(endword == '룩'){
endword2 = '눅'
} else if(endword == '릭'){
endword2 = '익'
} else if(endword == '롬'){
endword2 = '놈'
} else if(endword == '닝'){
endword2 = '잉'
} else if(endword == '롭'){
endword2 = '놉'
} else if(endword == '룻'){
endword2 = '눗'
} else if(endword == '롄'){
endword2 = '옌'
} else if(endword == '닉'){
endword2 = '익'
} else if(endword == '렷'){
endword2 = '엿'
} else if(endword == '닌'){
endword2 = '인'
} else if(endword == '릇'){
endword2 = '늣'
} else if(endword == '륨'){
endword2 = '윰'
} else if(endword == '론'){
endword2 = '논'
} else if(endword == '룅'){
endword2 = '뇡'
} else if(endword == '닙'){
endword2 = '입'
} else if(endword == '늄'){
endword2 = '윰'
}
return(endword2)
}
[결과]
참고 문헌
[논문]
- 없음
[보고서]
- 없음
[URL]
- 없음
문의사항
[기상학/프로그래밍 언어]
- sangho.lee.1990@gmail.com
[해양학/천문학/빅데이터]
- saimang0804@gmail.com
'프로그래밍 언어 > R' 카테고리의 다른 글
[R] WRF 모델자료 후처리 시퀀스1 - nc 파일을 풀어 txt 형태로 떨어뜨리기 (0) | 2021.01.27 |
---|---|
[R] 온라인 리눅스 (Linux) 환경에서 R 및 R Studio 설치/업데이트 (0) | 2021.01.27 |
[R] WRF 모델 자료로부터 기상 변수 추출 및 단열선도 시각화 그리고 RadioSonde 패키지 내 단열선도 X축 커스터마이징 (켈빈 to 섭씨) (0) | 2021.01.18 |
[R] 시정거리 자료를 이용한 한반도 지역 등고선 (Contour) 시각화 및 해양 마스킹 (2) | 2021.01.17 |
[R] 베이지안 선형회귀 모델을 통한 ASOS 종관 기상 관측지점 자료를 이용하여 AWS 관측 지점의 기온 추정 (0) | 2021.01.17 |
최근댓글