서비스 기획자의 성장기록

[R 실습] dataset에서 숫자를 값으로 가진 열의 합계와 평균 반환하기 본문

R/R 실습

[R 실습] dataset에서 숫자를 값으로 가진 열의 합계와 평균 반환하기

Jenny Noh 2023. 10. 5. 19:31

Q. 특정 dts(df, dataframe)을 인수로 입력하면, 숫자 변수 (컬럼) 내용만 조회하여 합계와 평균을 출력하는 함수 개발

 

데이터 셋

테스트로 사용할 데이터 셋은 아래의 'ss_exam.csv' 파일입니다. 

학생 id 별로 반과 database, java, 일본어, 영어 시험 성적을 입력해 놓은 파일입니다. 

ss_exam.csv
0.00MB

 

스크립트 1: 테스트 데이터를 사용하여 함수 내용 작성하기

examdts <- read.csv("dts/ss_exam.csv")

sum_total <- c()
avg_total <- c()
col_name <- c()

for(i in 1:length(names(examdts))){
  if(class(examdts[[i]])=="integer"){
    sum_col <- sum(examdts[[i]])
    avg_col <- round(mean(examdts[[i]]), 2)
    
    cat(paste(names(examdts)[i], "의", "합계는", sum_col, "평균은", avg_col), fill = 1)
    
    sum_total <- c(sum_total, sum_col)
    avg_total <- c(avg_total, avg_col)
    col_name <- c(col_name, names(examdts[i]))
  }
}
sum_dts <- data.frame(col_name, sum_total, avg_total)
write.csv(sum_dts, "dts/sum_exam.csv")

먼저 데이터 셋으로 사용할 파일을 불러와서 'examdts'라는 변수에 저장해줍니다.

examdts <- read.csv("dts/ss_exam.csv")

 

산출된 값으로 데이터 프레임을 만들것이기 때문에, 데이터 프레임 생성 함수에서 변수로 입력할 객체들을 벡터 형태로 정의해 줍니다.

sum_total <- c()
avg_total <- c()
col_name <- c()

 

아래의 순서로 문제를 풀어보겠습니다.

1) 조건 (=값이 숫자형인 열)에 해당하는 열 찾기

2) 해당 열의 합계와 평균 구하기

3) 각 열에 대한 연산 값과 열 이름을 변수 벡터에 추가하기

4) 저장된 벡터값들을 데이터 프레임 형태로 변환하기

5) 원하는 폴더에 csv 파일 생성하기

 

 

모든 열에 대해서 연산을 진행할 것이기 때문에 for 문을 사용하여 (i = 1) 번째 열에서 (i = 마지막) 번째 열까지 연산을 반복해 줍니다. 

for(i in 1:length(names(examdts)))

이 때, 열의 갯수를 구하기 위해 데이터셋의 열 이름을 반환하는 함수인 names( )함수에 length( ) 함수를 걸어줍니다.

 

1) 조건 (=값이 숫자형인 열)에 해당하는 열 찾기

if(class(examdts[[i]])=="integer"){

 

2) 해당 열의 합계와 평균 구하기

    sum_col <- sum(examdts[[i]])
    avg_col <- round(mean(examdts[[i]]), 2)

각 열의 값들의 합계와 평균을 계산하여 각각 변수 'sum_col'과 'avg_col'에 저장해 줍니다.

 

이 때, 값들이 잘 연산되었는지 확인하기 위해 cat( ) 함수로 출력해줍니다.

cat(paste(names(examdts)[i], "의", "합계는", sum_col, "평균은", avg_col), fill = 1)

 

3) 각 열에 대한 연산 값과 열 이름을 변수 벡터에 추가하기

    sum_total <- c(sum_total, sum_col)
    avg_total <- c(avg_total, avg_col)
    col_name <- c(col_name, names(examdts[i]))

데이터 프레임을 만들기 위해 생성했던 벡터 변수들에 '열 이름', '합계', '평균' 값을 입력해 줍니다.

 

 

4) 저장된 벡터값들을 데이터 프레임 형태로 변환하기

sum_dts <- data.frame(col_name, sum_total, avg_total)

벡터값들을 활용해 데이터 프레임을 생성한 후, sum_dts 변수에 할당해 줍니다.

 

 

5) 원하는 폴더에 csv 파일 생성하기

write.csv(sum_dts, "dts/sum_exam.csv")

csv 파일을 생성하기 위해 write.csv 함수를 사용해줍니다. 

저는 현재 워크디렉토리 폴더 안의 dts라는 폴더에 저장할 것이기 때문에 상대주소를 해당 폴더로 설정해 주었습니다.

 

 

 

스크립트 2: 함수 만들기

numcolsum <- function(a){
  sum_total <- c()
  avg_total <- c()
  col_name <- c()
  
  for(i in 1:length(names(a))){
    if((class(a[[i]])=="integer") | (class(a[[i]]) == "numeric")){
      sum_col <- sum(a[[i]])
      avg_col <- round(mean(a[[i]]), 2)
      
      cat(paste(names(a)[i], "의", "합계는", sum_col, "평균은", avg_col), fill = 1)
      
      sum_total <- c(sum_total, sum_col)
      avg_total <- c(avg_total, avg_col)
      col_name <- c(col_name, names(a[i]))
    }
  }
  
  new_table <- data.frame(col_name, sum_total, avg_total)
  write.csv(new_table, "dts/new_table.csv")
  return(new_table)
}

함수 이름을 numcolsum으로 지정하여 매개변수 a (=데이터 셋 넣을 장소)를 사용한 함수를 정의해 주었습니다. 

if 절의 조건 부분에서 실수 값도 포함하기 위해 class(a[[i]]) 값이 integer 이거나 class(a[[i]]) 값이 numeric 이라는 조건을 추가해주었습니다. 

if((class(a[[i]])=="integer") | (class(a[[i]]) == "numeric"))

더 큰 범위로 한 번에 쓸 수 있을 것 같은데 일단 각 열을 class 함수로 돌려봤을 때 integer와 numeric 두 값으로 나와서 or 연산자로 걸어주었습니다. 😅

 

결과값

ggplot2 패키지 안의 mpg 데이터를 활용하여 함수를 돌려보겠습니다. 

numcolsum(ggplot2::mpg) |> View()

 

콘솔에 출력되는 값: 

결과값 View( ) 결과:

 

그리고 폴더에 새로 'new_table'이라는 cvs 파일이 생성되었습니다. 

new_table.csv
0.00MB

 

 

 

sapply, colSums, colMeans 함수를 사용해서 for 문 안쓰고 더 간단하게 하는 방법도 있습니다.

그것은 다음에..