R 에서 각 변수간 그룹의 평균값을 계산하여 새로운 열에 삽입해 보자


아래와 같은 데이터가 있습니다.

treatment=rep(c("A","B","C","D","E"), each=3)<br>rep=rep(c("I","II","III"), time=5)<br>yield=c(10,11,21,13,23,23,13,13,5,33,21,13,42,12,13)<br>dataA=data.frame(treatment,rep, yield)<br><br>dataA<br>   treatment rep yield<br>1          A   I    10<br>2          A  II    11<br>3          A III    21<br>4          B   I    13<br>5          B  II    23<br>6          B III    23<br>7          C   I    13<br>8          C  II    13<br>9          C III     5<br>10         D   I    33<br>11         D  II    21<br>12         D III    13<br>13         E   I    42<br>14         E  II    12<br>15         E III    13

이 데이터에서 treatment 별로 평균값을 계산하여 새로운 열에 삽입하고 싶습니다. 그래서 아래와 같은 코드를 사용해 보겠습니다.

dataA$mean= NA #to create an empty column<br><br>dataA$mean[dataA$treatment=="A"]=mean(dataA$yield[dataA$treatment=="A"], na.rm=TRUE)<br>dataA$mean[dataA$treatment=="B"]=mean(dataA$yield[dataA$treatment=="B"], na.rm=TRUE)<br>dataA$mean[dataA$treatment=="C"]=mean(dataA$yield[dataA$treatment=="C"], na.rm=TRUE)<br>dataA$mean[dataA$treatment=="D"]=mean(dataA$yield[dataA$treatment=="D"], na.rm=TRUE)<br>dataA$mean[dataA$treatment=="E"]=mean(dataA$yield[dataA$treatment=="E"], na.rm=TRUE)<br><br>dataA<br>   treatment rep yield     mean<br>1          A   I    10 14.00000<br>2          A  II    11 14.00000<br>3          A III    21 14.00000<br>4          B   I    13 19.66667<br>5          B  II    23 19.66667<br>6          B III    23 19.66667<br>7          C   I    13 10.33333<br>8          C  II    13 10.33333<br>9          C III     5 10.33333<br>10         D   I    33 22.33333<br>11         D  II    21 22.33333<br>12         D III    13 22.33333<br>13         E   I    42 22.33333<br>14         E  II    12 22.33333<br>15         E III    13 22.33333


하지만 이 코드는 너무 길어 보입니다. 아주 간편하게 위와 동일한 계산을 수행하는 코드가 있으면 아주 편할것 같습니다. tapply() 코드는 위와 동일한 계산을 가능하게 하는 코드입니다. mean2 라는 열을 생성해서 그곳에 각 변수의 평균값을 계산하여 삽입하고 싶습니다.

library(base)<br>dataA$mean2=tapply(dataA$yield, dataA$treatment, mean, na.rm=TRUE)[dataA$treatment]<br><br>dataA<br>   treatment rep yield     mean    mean2<br>1          A   I    10 14.00000 14.00000<br>2          A  II    11 14.00000 14.00000<br>3          A III    21 14.00000 14.00000<br>4          B   I    13 19.66667 19.66667<br>5          B  II    23 19.66667 19.66667<br>6          B III    23 19.66667 19.66667<br>7          C   I    13 10.33333 10.33333<br>8          C  II    13 10.33333 10.33333<br>9          C III     5 10.33333 10.33333<br>10         D   I    33 22.33333 22.33333<br>11         D  II    21 22.33333 22.33333<br>12         D III    13 22.33333 22.33333<br>13         E   I    42 22.33333 22.33333<br>14         E  II    12 22.33333 22.33333<br>15         E III    13 22.33333 22.33333

첫번째 일일이 계산했던 방법과 동일한 값을 얻을 수 있습니다. 즉, 아래와 같이 길었던 코드와 동일한 계산식을 제공하는 코드가 tapply() 입니다.

dataA$mean[dataA$treatment=="A"]=mean(dataA$yield[dataA$treatment=="A"], na.rm=TRUE)
dataA$mean[dataA$treatment=="B"]=mean(dataA$yield[dataA$treatment=="B"], na.rm=TRUE)
dataA$mean[dataA$treatment=="C"]=mean(dataA$yield[dataA$treatment=="C"], na.rm=TRUE)
dataA$mean[dataA$treatment=="D"]=mean(dataA$yield[dataA$treatment=="D"], na.rm=TRUE)
dataA$mean[dataA$treatment=="E"]=mean(dataA$yield[dataA$treatment=="E"], na.rm=TRUE)
                                       ↓
dataA$mean2=tapply(dataA$yield, dataA$treatment, mean, na.rm=TRUE)[dataA$treatment]


만일 변수가 하나가 아니라 여러개일 경우 그 변수간 조합의 평균을 계산하고 싶을 때는 어떻게 해야 할까요?

treatment=rep(rep(c("A","B","C","D","E"), each=3),2)<br>rep=rep(rep(c("I","II","III"), time=5),2)<br>environment=rep(c("East","West","North"), each=10)<br>yield=c(10,11,21,13,23,23,13,13,5,33,21,13,42,12,13,10,11,54,45,39,33,29,43,55,33,24,32,42,28,43)<br>dataA=data.frame(treatment,rep, environment, yield)<br><br>dataA<br>   treatment rep environment yield     mean<br>1          A   I        East    10 14.00000<br>2          A  II        East    11 14.00000<br>3          A III        East    21 14.00000<br>4          B   I        East    13 19.66667<br>5          B  II        East    23 19.66667<br>6          B III        East    23 19.66667<br>7          C   I        East    13 10.33333<br>8          C  II        East    13 10.33333<br>9          C III        East     5 10.33333<br>10         D   I        East    33 33.00000<br>11         D  II        West    21 17.00000<br>12         D III        West    13 17.00000<br>13         E   I        West    42 22.33333<br>14         E  II        West    12 22.33333<br>15         E III        West    13 22.33333<br>16         A   I        West    10 25.00000<br>17         A  II        West    11 25.00000<br>18         A III        West    54 25.00000<br>19         B   I        West    45 42.00000<br>20         B  II        West    39 42.00000<br>21         B III       North    33 33.00000<br>22         C   I       North    29 42.33333<br>23         C  II       North    43 42.33333<br>24         C III       North    55 42.33333<br>25         D   I       North    33 29.66667<br>26         D  II       North    24 29.66667<br>27         D III       North    32 29.66667<br>28         E   I       North    42 37.66667<br>29         E  II       North    28 37.66667<br>30         E III       North    43 37.66667

이제는 treatment 와 environment 간 조합 (i.e., A and East) 의 평균을 구하고 싶습니다. 아래와 같이 코드를 작성합니다.

library(base)<br>dataA$mean=tapply(dataA$yield, list(dataA$treatment, dataA$environment), mean, na.rm=TRUE)[cbind(dataA$treatment, dataA$environment)]<br><br>dataA<br>   treatment rep environment yield mean<br>1          A   I        East    10 14.00000<br>2          A  II        East    11 14.00000<br>3          A III        East    21 14.00000<br>4          B   I        East    13 19.66667<br>5          B  II        East    23 19.66667<br>6          B III        East    23 19.66667<br>7          C   I        East    13 10.33333<br>8          C  II        East    13 10.33333<br>9          C III        East     5 10.33333<br>10         D   I        East    33 33.00000<br>11         D  II        West    21 17.00000<br>12         D III        West    13 17.00000<br>13         E   I        West    42 22.33333<br>14         E  II        West    12 22.33333<br>15         E III        West    13 22.33333<br>16         A   I        West    10 25.00000<br>17         A  II        West    11 25.00000<br>18         A III        West    54 25.00000<br>19         B   I        West    45 42.00000<br>20         B  II        West    39 42.00000<br>21         B III       North    33 33.00000<br>22         C   I       North    29 42.33333<br>23         C  II       North    43 42.33333<br>24         C III       North    55 42.33333<br>25         D   I       North    33 29.66667<br>26         D  II       North    24 29.66667<br>27         D III       North    32 29.66667<br>28         E   I       North    42 37.66667<br>29         E  II       North    28 37.66667<br>30         E III       North    43 37.66667

treatment A 와 West 에서의 평균이 과연 25가 맞는지 검증해 보겠습니다.

mean (dataA$yield[dataA$treatment=="A" & dataA$environment=="West"], na.rm=TRUE)
# 25

평균값은 25 라고 합니다. 위에서 tapply() 코드로 계산된 값과 동일한 값 입니다.


Step-by-Step Guide to Calculating and Adding Variable Means in R