컴퓨터/R 공부

(코드 오류와 해결 기록) dcast() : Aggregation function missing: defaulting to length

방구석의 개굴이 2023. 7. 19. 09:58

혼공R이 p254 풀던 중 예시와 달리 앞 챕터에서 만든 데이터프레임을 dcast() 함수에 집어넣었더니

Aggregation function missing: defaulting to length

이런 오류가 나왔다 (티스토리는 이게 오류 코드인지 그냥 코드인지는 인식 못하고 그냥 글자대로만 인식하는 걸까?)

chat GPT한테도 물어봤는데 표면적으로만 해결하고 본질적인 문제는 해결하지 못해서 결국 추가적으로 공부를 하게 되었다. 

오류의 원인을 알기 위해서는 (1) aggregation 함수, (2) length 함수, (3) "wind"와 "day"의 차이를 알아야하고 또 코드를 조금씩 바꿔서 실행해본 결과를 비교해서 오류를 해결할 수 있다. 

 

오류의 원인 : 기본 지식

(1) aggregation() 함수

dcast() 함수를 실행하면 자동적으로 적용되는 옵션 중 하나인 aggregation() 함수는 R 기본함수 중 하나이다. 

aggregate는 데이터의 특정 컬럼을 기준으로 통계량(FUN옵션에서 적용. mean, sum 등)을 구해주는 함수이다. 

  • data frame에 적용할 때 코드
aggregate(data, by = '기준이 되는 컬럼', FUN)
> aggregate(airquality, list(reference.month = airquality$month), length)
  reference.month ozone solar.r wind temp month day
1               5    31      31   31   31    31  31
2               6    30      30   30   30    30  30
3               7    31      31   31   31    31  31
4               8    31      31   31   31    31  31
5               9    30      30   30   30    30  30

month를 reference로 새로운 컬럼을 형성했고 이걸 기준으로 각각의 변수에 대한 length를 세었다.

 

  • 변수에 대해 formula를 적용할 때 코드
aggregate('함수를 적용하고자 하는 컬럼' ~ '기준이 되는 컬럼', data, FUN)
ex_aggregate <- aggregate(data = airquality, month + day ~ solar.r, length)
View(ex_aggregate)

코드가 비슷하니 결과도 비슷할 것 같지만 전혀 다른 결과가 나왔다. 

> aggregate(airquality, month + day ~ solar.r)
Error in match.fun(FUN) : argument "FUN" is missing, with no default
> aggregate(airquality, month + day ~ solar.r, length)
Error in aggregate.data.frame(airquality, month + day ~ solar.r, length) : 
  'by' must be a list

이 결과를 얻으려다 나온 오류도 분석하고 싶지만 그러면 진도를 또 못 나갈 것 같으니 일단 패스 

 

결론적으로  aggregate() 함수는 특정(하나 혹은 여러 개) 열을 기준으로 나머지 모든 열 또는 몇 개 열을 조건에 맞게 합쳐주는 함수이다. 

 

https://m.blog.naver.com/coder1252/221294821930

 

R - 기본함수 - aggregate

                &nbs...

blog.naver.com

참고한 블로그

 

(2) length() 함수

벡터의 길이, 데이터프레임의 열의 개수(통계 용어로는 빈도수)를 셀 때 사용하는 함수

> ex_vector1 <- c(1,2,3,4,5,6,7)
> ex_vector2 <- c(2,4,6,8,10,12,14)
> ex_vector3 <- c(3,6,9,12,15,18,21)
> length(ex_vector1)
[1] 7

> ex_dataframe <- data.frame(ex_vector1, ex_vector2, ex_vector3)
> length(ex_dataframe$ex_vector1)
[1] 7

> ex_dataframe
  ex_vector1 ex_vector2 ex_vector3
1          1          2          3
2          2          4          6
3          3          6          9
4          4          8         12
5          5         10         15
6          6         12         18
7          7         14         21

(3) "wind"열과 "day"열의 차이

> head(airquality)
  ozone solar.r wind temp month day
1    41     190  7.4   67     5   1
2    36     118  8.0   72     5   2
3    12     149 12.6   74     5   3
4    18     313 11.5   62     5   4
5    NA      NA 14.3   56     5   5
6    28      NA 14.9   66     5   6

- wind는 실수형, day는 정수형

- wind는 겹치는 게 논리적 의미가 없는 반면 day는 서로 같아도 month가 다르며 month와 day는 서로 다른 날짜를 가리킴

 

오류의 원인 : 결과 관찰
> # 앞 예제에서 사용했던 코드
> melt_test1 <- melt(airquality, id.vars = c("month", "wind"),
+                    measure.vars = "ozone")
> dcast_test1 <- dcast(melt_test1, month + wind ~ variable)
Aggregation function missing: defaulting to length
> 
> head(dcast_test1)
  month wind ozone
1     5  5.7     1
2     5  6.9     1
3     5  7.4     2
4     5  8.0     2
5     5  8.6     2
6     5  9.2     1
> tail(dcast_test1)
   month wind ozone
83     9 13.2     1
84     9 13.8     1
85     9 14.3     1
86     9 14.9     1
87     9 15.5     2
88     9 16.6     1

# 문제 : measure variable이 ozone 뿐이므로 dcast를 적용해도 원래대로 돌아오지 않음
+ 기본함수인 length 가 적용되므로 ozone의 농도가 아니라 관측된 행의 수만 결과로 반환됨. 
(ex. month = 5이고 wind - 5.7 인 날 ozone 이 채워진 행은 한 개 :: ozone =1)
+ 차라리 mean으로 설정하면 유의미함 

> # 이번 예제에서 새로 만든 코드
> melt_test2 <- melt(airquality, id.vars = c("month", "day"))
> dcast_test2 <- dcast(melt_test2, month + day ~ variable)
> 
> head(dcast_test2)
  month day ozone solar.r wind temp
1     5   1    41     190  7.4   67
2     5   2    36     118  8.0   72
3     5   3    12     149 12.6   74
4     5   4    18     313 11.5   62
5     5   5    NA      NA 14.3   56
6     5   6    28      NA 14.9   66
> tail(dcast_test2)
    month day ozone solar.r wind temp
148     9  25    14      20 16.6   63
149     9  26    30     193  6.9   70
150     9  27    NA     145 13.2   77
151     9  28    14     191 14.3   75
152     9  29    18     131  8.0   76
153     9  30    20     223 11.5   68

# 문제가 발생하지 않는 이유 : month + day를 reference로 잡으면 각각의 행이 identify 되어서 
fun.aggregate가 length로 적용되지 않고 원래 값을 적어주는듯? 
확실하게는 실제 코드 실행과정을 봐야겠지만...
> 
> # 두 개를 절충한(?) 코드
> melt_test3 <- melt(airquality, id.vars = c("month", "wind"))
> dcast_test3 <- dcast(melt_test3, month + wind ~ variable)
Aggregation function missing: defaulting to length
> 
> head(dcast_test3)
  month wind ozone solar.r temp day
1     5  5.7     1       1    1   1
2     5  6.9     1       1    1   1
3     5  7.4     2       2    2   2
4     5  8.0     2       2    2   2
5     5  8.6     2       2    2   2
6     5  9.2     1       1    1   1
> tail(dcast_test3)
   month wind ozone solar.r temp day
83     9 13.2     1       1    1   1
84     9 13.8     1       1    1   1
85     9 14.3     1       1    1   1
86     9 14.9     1       1    1   1
87     9 15.5     2       2    2   2
88     9 16.6     1       1    1   1

# 첫번째와 같이 fun.aggregate = length로 적용되어서 데이터가 날아갔다. 

> dcast_test3.1 <- dcast(melt_test3, month + wind ~ variable, fun.aggregate = mean)
> head(dcast_test3.1)
  month wind ozone solar.r temp  day
1     5  5.7   115   223.0 79.0 30.0
2     5  6.9     7      NA 74.0 11.0
3     5  7.4    39   234.5 71.5 16.0
4     5  8.0    NA      NA 64.5 14.5
5     5  8.6    NA   246.5 67.0  8.5
6     5  9.2    11   290.0 66.0 13.0

# 이렇게 하면 순서는 좀 뒤죽박죽이고 day 가 실수형으로 출력되는 문제가 있기는 하지만 
비교적 비슷하게 데이터를 복원할 수 있다.
오류의 해결

각각의 행이 의미 있으려면 month + day ~ variable 로 코드를 작성해주는 것이 맞다. 하지만 굳이 원래 코드를 쓰면서 데이터를 유지하고 싶다면 fun.aggregate = mean으로 해주면 됨

 

여담

보통의 오류는 그냥 R studio를 껐다가 켜면 그냥 해결됨.