범주 형 변수 차트에서 개수 대신 % 표시


170

범주 형 변수를 플로팅하고 각 범주 값의 개수를 표시하는 대신

ggplot해당 범주에서 값의 백분율을 표시 하는 방법을 찾고 있습니다. 물론, 계산 된 백분율로 다른 변수를 만들고 그 변수를 플롯 할 수는 있지만 수십 번 수행해야하며 한 명령으로이를 달성하기를 바랍니다.

나는 다음과 같은 것을 실험하고 있었다.

qplot(mydataf) +
  stat_bin(aes(n = nrow(mydataf), y = ..count../n)) +
  scale_y_continuous(formatter = "percent")

하지만 오류가 발생하여 잘못 사용해야합니다.

설정을 쉽게 재현 할 수있는 간단한 예는 다음과 같습니다.

mydata <- c ("aa", "bb", NULL, "bb", "cc", "aa", "aa", "aa", "ee", NULL, "cc");
mydataf <- factor(mydata);
qplot (mydataf); #this shows the count, I'm looking to see % displayed.

실제 경우에는 아마도을ggplot 대신 사용 qplot하지만 stat_bin 을 사용하는 올바른 방법은 여전히 탈피 합니다.

나는 또한이 네 가지 접근법을 시도했다.

ggplot(mydataf, aes(y = (..count..)/sum(..count..))) + 
  scale_y_continuous(formatter = 'percent');

ggplot(mydataf, aes(y = (..count..)/sum(..count..))) + 
  scale_y_continuous(formatter = 'percent') + geom_bar();

ggplot(mydataf, aes(x = levels(mydataf), y = (..count..)/sum(..count..))) + 
  scale_y_continuous(formatter = 'percent');

ggplot(mydataf, aes(x = levels(mydataf), y = (..count..)/sum(..count..))) + 
  scale_y_continuous(formatter = 'percent') + geom_bar();

그러나 4 개 모두는 :

Error: ggplot2 doesn't know how to deal with data of class factor

간단한 경우에 동일한 오류가 나타납니다.

ggplot (data=mydataf, aes(levels(mydataf))) +
  geom_bar()

ggplot단일 벡터와 상호 작용 하는 방식 에 관한 것 입니다. 나는 머리를 긁고 있는데, 그 오류에 대한 인터넷 검색은 단일 결과를 제공합니다 .


2
데이터는 단순한 요소가 아닌 데이터 프레임이어야합니다.
hadley

1
hadley의 의견을 추가하고, mydataf = data.frame (mydataf)를 사용하여 데이터를 데이터 프레임으로 변환하고, 이름을 myname (mydataf) = foo로 바꾸면 속임수가됩니다
Ramnath

답변:


221

이것이 답변 된 이후 ggplot구문에 의미있는 변화가있었습니다 . 위의 의견에서 토론을 요약하면 다음과 같습니다.

 require(ggplot2)
 require(scales)

 p <- ggplot(mydataf, aes(x = foo)) +  
        geom_bar(aes(y = (..count..)/sum(..count..))) + 
        ## version 3.0.0
        scale_y_continuous(labels=percent)

다음을 사용하여 재현 가능한 예는 다음과 같습니다 mtcars.

 ggplot(mtcars, aes(x = factor(hp))) +  
        geom_bar(aes(y = (..count..)/sum(..count..))) + 
        scale_y_continuous(labels = percent) ## version 3.0.0

여기에 이미지 설명을 입력하십시오

이 질문은 현재 구글에서 'ggplot count vs percent histogram'에서 1 위를 차지 했으므로 현재 승인 된 답변에 대한 의견에 포함 된 모든 정보를 증류하는 데 도움이되기를 바랍니다.

비고 :hp 인자로 설정되지 않은 경우 ggplot은 다음을 반환합니다.

여기에 이미지 설명을 입력하십시오


12
이 답변에 감사드립니다. 클래스 단위로 수행하는 방법에 대한 아이디어가 있습니까?
WAF

3
. @ WAF에서 알 수 있듯이이 답변은 패싯 데이터에는 작동하지 않습니다. 에서 유안의 의견 @보기 stackoverflow.com/questions/22181132/...
LeeZamparo

1
percent위의 작업을 수행하려면 원래 패키지 를 접두사 로 사용해야 할 수도 있습니다 . ggplot(mtcars, aes(x = factor(hp))) + geom_bar(aes(y = (..count..)/sum(..count..))) + scale_y_continuous(labels = scales::percent)
mammykins

패싯 사용을 피하려면 geom_bar(aes(y = (..count..)/tapply(..count..,..PANEL..,sum)[..PANEL..]))대신 사용하십시오. 각 패싯의 합계는 100 % 여야합니다.
JWilliman

주변에 ".."가있는 변수가 stat () 명령으로 바뀌지 않았습니까? ggplot2.tidyverse.org/reference/stat.html
Magnus

58

이 수정 된 코드는 작동해야합니다

p = ggplot(mydataf, aes(x = foo)) + 
    geom_bar(aes(y = (..count..)/sum(..count..))) + 
    scale_y_continuous(formatter = 'percent')

데이터에 NA가 있고 플롯에 포함하지 않으려면 na.omit (mydataf)를 ggplot의 인수로 전달하십시오.

도움이 되었기를 바랍니다.


37
ggplot2 버전 0.9.0에서는 formatter인수가 더 이상 작동하지 않습니다. 대신, 당신은 같은 것을 원할 것 labels = percent_format())입니다.
joran

25
0.9.0에서는을 scales사용하기 전에 라이브러리 를로드해야합니다 percent_format(). 그렇지 않으면 작동하지 않습니다. 0.9.0은 더 이상 지원 패키지를 자동으로로드하지 않습니다.
Andrew

1
참조하십시오 ? stat_bin. 로 데이터 프레임에 추가되는 추가 열을 보여줍니다 ggplot2. 모든 추가 열은 형식 ..variable..입니다.
Ramnath

1
aes(y = (..count..)/sum(..count..))간단하게 대체하는 것이 합리적 aes(y = ..density..)입니까? 시각적으로 매우 비슷한 (하지만 여전히 다른) 사진을 제공
알렉산더 Kosenkov에게

6
ggplot 0.9.3.1.0에서는 먼저 scales라이브러리를 로드 한 다음 문서에scale_y_continuous(labels=percent) 언급
adilapapaya


37

2017 년 3 월 현재 ggplot22.2.1에서 최고의 솔루션은 Hadley Wickham의 R에 대한 데이터 과학 책에 설명되어 있습니다.

ggplot(mydataf) + stat_count(mapping = aes(x=foo, y=..prop.., group=1))

stat_count두 변수를 계산합니다. count기본적으로 사용되지만 prop비율을 표시하는 것을 사용하도록 선택할 수 있습니다 .


3
이것은 2017 년 6 월 현재 가장 좋은 답변이며 그룹별로 채우고 패싯 처리합니다.
Skumin 2016 년

1
어떤 이유로 든 fill매핑 을 사용할 수 없습니다 (오류가 발생하지 않지만 채우기 색상이 추가되지 않음).
맥스 칸도 키아

@MaxCandocia group = 1채우기 매핑을 얻으려면 제거해야했습니다 . 아마 도움이 될 것입니다
Tjebo

1
그러나 group매개 변수를 제거하면 모든 고유 x 값에 대해 모든 것이 자체 그룹에 속하기 때문에 적절한 백분율이 표시되지 않습니다.
Max Candocia

20

당신은 y 축에 대한 비율을 원하는 경우 막대에 표시 :

library(ggplot2)
library(scales)
ggplot(mtcars, aes(x = as.factor(am))) +
  geom_bar(aes(y = (..count..)/sum(..count..))) +
  geom_text(aes(y = ((..count..)/sum(..count..)), label = scales::percent((..count..)/sum(..count..))), stat = "count", vjust = -0.25) +
  scale_y_continuous(labels = percent) +
  labs(title = "Manual vs. Automatic Frequency", y = "Percent", x = "Automatic Transmission")

여기에 이미지 설명을 입력하십시오

막대 레이블을 추가 할 때 끝을 추가하여 더 깨끗한 차트의 y 축을 생략 할 수 있습니다.

  theme(
        axis.text.y=element_blank(), axis.ticks=element_blank(),
        axis.title.y=element_blank()
  )

여기에 이미지 설명을 입력하십시오


6

y 축에서 백분율 레이블을 제외한 실제 N 을 원하면 다음을 시도하십시오.

    library(scales)
perbar=function(xx){
      q=ggplot(data=data.frame(xx),aes(x=xx))+
      geom_bar(aes(y = (..count..)),fill="orange")
       q=q+    geom_text(aes(y = (..count..),label = scales::percent((..count..)/sum(..count..))), stat="bin",colour="darkgreen") 
      q
    }
    perbar(mtcars$disp)

6

패싯 데이터에 대한 해결 방법은 다음과 같습니다. (이 경우 @Andrew의 답변은 작동하지 않습니다.) 아이디어는 dplyr을 사용하여 백분율 값을 계산 한 다음 geom_col을 사용하여 플롯을 만드는 것입니다.

library(ggplot2)
library(scales)
library(magrittr)
library(dplyr)

binwidth <- 30

mtcars.stats <- mtcars %>%
  group_by(cyl) %>%
  mutate(bin = cut(hp, breaks=seq(0,400, binwidth), 
               labels= seq(0+binwidth,400, binwidth)-(binwidth/2)),
         n = n()) %>%
  group_by(cyl, bin) %>%
  summarise(p = n()/n[1]) %>%
  ungroup() %>%
  mutate(bin = as.numeric(as.character(bin)))

ggplot(mtcars.stats, aes(x = bin, y= p)) +  
  geom_col() + 
  scale_y_continuous(labels = percent) +
  facet_grid(cyl~.)

이것은 음모입니다.

여기에 이미지 설명을 입력하십시오


3

변수가 연속적인 경우 함수는 변수를 "bins"로 그룹화하므로 geom_histogram ()을 사용해야합니다.

df <- data.frame(V1 = rnorm(100))

ggplot(df, aes(x = V1)) +  
  geom_histogram(aes(y = (..count..)/sum(..count..))) 

# if you use geom_bar(), with factor(V1), each value of V1 will be treated as a
# different category. In this case this does not make sense, as the variable is 
# really continuous. With the hp variable of the mtcars (see previous answer), it 
# worked well since hp was not really continuous (check unique(mtcars$hp)), and one 
# can want to see each value of this variable, and not to group it in bins.
ggplot(df, aes(x = factor(V1))) +  
  geom_bar(aes(y = (..count..)/sum(..count..))) 
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.