ggplot2 막대 그래프의 주문 막대


301

가장 큰 막대가 y 축에 가장 가깝고 가장 짧은 막대가 가장 먼 막대 그래프를 만들려고합니다. 그래서 이것은 제가 가지고있는 테이블과 같습니다.

    Name   Position
1   James  Goalkeeper
2   Frank  Goalkeeper
3   Jean   Defense
4   Steve  Defense
5   John   Defense
6   Tim    Striker

위치에 따라 플레이어 수를 나타내는 막대 그래프를 만들려고합니다.

p <- ggplot(theTable, aes(x = Position)) + geom_bar(binwidth = 1)

그러나 그래프는 먼저 골키퍼 막대를 보여주고 방어와 마지막으로 스트라이커를 보여줍니다. 방어 막대가 y 축, 골키퍼, 마지막으로 스트라이커에 가장 가깝도록 그래프를 정렬하고 싶습니다. 감사


12
ggplot이 테이블 (또는 데이터 프레임)을 엉망으로 만들지 않고도 재정렬 할 수 있습니까?
— tumultous_rooster

1
@ MattO'Brien 나는 이것이 하나의 간단한 명령으로 이루어지지 않았다는 것을 믿을 수 없다
— Euler_Salter

@ Zimano 너무 나쁘다는 것이 내 의견에서 얻는 것입니다. 내 관찰은 ggplot2OP가 아닌 의 제작자에 대한 것이었다
— Euler_Salter

2
@Euler_Salter 명확하게 해주셔서 감사합니다. 진심으로 사과드립니다. 원래 의견을 삭제했습니다.
— Zimano

답변:


214

순서의 핵심은 요인의 수준을 원하는 순서로 설정하는 것입니다. 주문 된 요소는 필요하지 않습니다. 정렬 된 요소의 추가 정보는 필요하지 않으며 이러한 데이터가 통계 모델에 사용되는 경우 잘못된 매개 변수가 발생할 수 있습니다. 다항식 대비는 이와 같은 명목 데이터에는 적합하지 않습니다.

## set the levels in order we want
theTable <- within(theTable, 
                   Position <- factor(Position, 
                                      levels=names(sort(table(Position), 
                                                        decreasing=TRUE))))
## plot
ggplot(theTable,aes(x=Position))+geom_bar(binwidth=1)

막대 그래프 그림

가장 일반적인 의미에서 요인 수준을 원하는 순서로 설정하면됩니다. 지정하지 않으면 요인의 수준이 알파벳순으로 정렬됩니다. 위와 같이 요소를 호출하여 수준 순서를 지정할 수도 있으며 다른 방법도 가능합니다.

theTable$Position <- factor(theTable$Position, levels = c(...))

1
@Gavin : 2 단순화 : 이미 사용 within하고 있기 때문에 사용할 필요가 없으며 주문을 줄이기 위해 theTable$Position할 수 있습니다 sort(-table(...)).
— Prasad Chalasani

2
@Prasad는 테스트에서 남은 부분이므로 지적 해 주셔서 감사합니다. 후자 -까지는 코드의 나머지 부분을 모두 decreasing = TRUE알아 차리는 것보다 의도를 얻는 것이 훨씬 쉽기 때문에 사용 하는 것 보다 반전 된 정렬을 명시 적으로 요청하는 것이 좋습니다 -.
— 개빈 심슨

2
@GavinSimpson; 나는 levels(theTable$Position) <- c(...)요소의 수준뿐만 아니라 데이터 프레임의 실제 항목이 재정렬되는 바람직하지 않은 행동으로 이어진다 고 생각합니다 . 이 질문을 참조하십시오 . 아마도 그 줄을 수정하거나 제거해야합니까?
— Anton

2
Anton에게 강력하게 동의하십시오. 방금 이 질문을 보고 그들이 사용하기에 나쁜 조언을 어디서 얻었는지 찾아 보았습니다 levels<-. 적어도 잠정적으로 그 부분을 편집 할 것입니다.
— Gregor Thomas

2
@Anton 제안을 해주셔서 감사합니다 (그리고 편집을 위해 Gregor에게); 나는 levels<-()오늘을 통해 이것을하지 않을 것 입니다. 이것은 8 년 전의 것이며, 당시와 다른 점이나 평범한 지 여부를 기억할 수는 없지만 관계없이 잘못되어 지워 져야합니다! 감사!
— Gavin Simpson

220

@GavinSimpson :이를 reorder위한 강력하고 효과적인 솔루션입니다 :

ggplot(theTable,
       aes(x=reorder(Position,Position,
                     function(x)-length(x)))) +
       geom_bar()

7
실제로 +1, 특히이 경우 수치 적으로 활용할 수있는 논리적 순서가있는 경우에 특히 그렇습니다. 카테고리의 임의 순서를 고려하고 사전 순을 원하지 않는 경우 표시된 것처럼 레벨을 직접 지정하는 것이 쉽습니다 (쉽습니까?).
— Gavin Simpson

2
이것은 가장 작은 것입니다. 원래 데이터 프레임을 수정해야 할 필요성을 무효로 함
— T.Fung

Lovely, 방금 길이 함수로 주문하고 오름차순으로 주문하는 것이 괜찮다면이 방법을 좀 더 간결하게 할 수 있다는 것을 알았습니다.ggplot(theTable,aes(x=reorder(Position,Position,length))+geom_bar()
— postylem

146

사용 scale_x_discrete (limits = ...)바의 순서를 지정할 수 있습니다.

positions <- c("Goalkeeper", "Defense", "Striker")
p <- ggplot(theTable, aes(x = Position)) + scale_x_discrete(limits = positions)

12
x는 data.frame의 변수로 표현되는 임의의 열로 플로팅하도록 프로그래밍하고 싶기 때문에 귀하의 솔루션은 내 상황에 가장 적합합니다. 다른 제안은 변수와 관련된 표현식으로 x 순서의 배열을 표현하기가 더 어려울 것입니다. 감사! 관심이 있다면 제안을 사용하여 솔루션을 공유 할 수 있습니다. scale_x_discrete (limits = ...)를 추가하는 또 하나의 문제는 차트 오른쪽에 막대 차트만큼 넓은 공백이 있다는 것을 알았습니다. 빈 공간을 없애려면 어떻게해야합니까? 목적을 달성하지 못하기 때문에.
— Yu Shen

이것은 막대 그래프 막대를 주문하는 데 필요한 것 같습니다
— 지리학

9
QIBIN : 와우 ​​... 여기의 다른 답변은 효과가 있지만, 귀하의 답변은 가장 간결하고 우아 할뿐만 아니라 ggplot의 프레임 워크에서 생각할 때 가장 분명합니다. 감사합니다.
— Dan Nguyen

이 솔루션을 시도했을 때 내 데이터에서 NA를 그래프로 나타내지 않았습니다. 이 솔루션을 사용하고 NA를 그래프로 표시하는 방법이 있습니까?
— user2460499

이것은 우아하고 간단한 해결책입니다-감사합니다 !!
— Kalif Vaughn

91

이미 제공된 솔루션이 지나치게 장황하다고 생각합니다. ggplot으로 주파수 정렬 막대 그래프를 수행하는 더 간결한 방법은

ggplot(theTable, aes(x=reorder(Position, -table(Position)[Position]))) + geom_bar()

Alex Brown이 제안한 것과 비슷하지만 조금 더 짧으며 임의의 함수 정의없이 작동합니다.

최신 정보

나는 이전의 해결책이 당시에는 좋았지 만 요즘에는 forcats::fct_infreq빈도별로 요인 수준을 정렬하는 것이 좋습니다 .

require(forcats)

ggplot(theTable, aes(fct_infreq(Position))) + geom_bar()

함수를 재정렬하는 두 번째 인수와 그 기능을 이해하지 못합니다. 무슨 일이 일어나고 있는지 친절하게 설명해 주시겠습니까?
— user3282777


1
훌륭한 솔루션! 깔끔한 솔루션을 사용하는 다른 사람들을 만나서 반갑습니다!
— Mike

29

마찬가지로 reorder()알렉스 브라운의 대답에, 우리는 또한 사용할 수 있습니다 forcats::fct_reorder(). 지정된 함수를 적용한 후 두 번째 인수의 값에 따라 기본적으로 첫 번째 인수에 지정된 요인을 정렬합니다 (기본값 = 중간 값, 여기서는 요인 수준 당 하나의 값을 갖는 것).

OP의 질문에서 필요한 순서도 요인을 만들 때 기본 정렬 순서이므로 알파벳순이므로이 함수가 실제로 수행하는 작업을 숨길 수 있습니다. 더 명확하게하기 위해 "Goalkeeper"를 "Zoalkeeper"로 바꾸겠습니다.

library(tidyverse)
library(forcats)

theTable <- data.frame(
                Name = c('James', 'Frank', 'Jean', 'Steve', 'John', 'Tim'),
                Position = c('Zoalkeeper', 'Zoalkeeper', 'Defense',
                             'Defense', 'Defense', 'Striker'))

theTable %>%
    count(Position) %>%
    mutate(Position = fct_reorder(Position, n, .desc = TRUE)) %>%
    ggplot(aes(x = Position, y = n)) + geom_bar(stat = 'identity')

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


1
forcats와 같은 IMHO 최고의 솔루션은 깔끔한 패키지입니다.
— c0bra

Zoalkeeper에 대한 승인
— otwtm

23

간단한 dplyr 기반 요인의 재정렬로이 문제를 해결할 수 있습니다.

library(dplyr)

#reorder the table and reset the factor to that ordering
theTable %>%
  group_by(Position) %>%                              # calculate the counts
  summarize(counts = n()) %>%
  arrange(-counts) %>%                                # sort by counts
  mutate(Position = factor(Position, Position)) %>%   # reset factor
  ggplot(aes(x=Position, y=counts)) +                 # plot 
    geom_bar(stat="identity")                         # plot histogram

19

레벨을 계수 로 정렬Position 한 순서화 된 요소 가되도록 열 을 지정하면 됩니다 .

theTable <- transform( theTable,
       Position = ordered(Position, levels = names( sort(-table(Position)))))

( table(Position)이는 Position열의 빈도 수를 생성합니다 .)

그런 다음 ggplot함수는 막대를 카운트 순서대로 표시합니다. geom_bar순서 인수를 명시 적으로 만들지 않고이 작업을 수행 할 수 있는 옵션이 있는지 모르겠습니다 .


코드를 완전히 파싱하지는 않았지만 reorder()통계 라이브러리에서 동일한 작업을 수행한다고 확신 합니다.
— 체이스

@Chase reorder()이 경우에 어떻게 사용을 제안 합니까? 재정렬이 필요한 요소는 자체 기능에 따라 재정렬해야하며 좋은 방법을 찾기 위해 고심하고 있습니다.
— Gavin Simpson

좋아, with(theTable, reorder(Position, as.character(Position), function(x) sum(duplicated(x))))하나의 방법, 그리고 다른 방법 with(theTable, reorder(Position, as.character(Position), function(x) as.numeric(table(x))))이지만 이것들은 복잡합니다 ...
— Gavin Simpson

내가 사용하는 약간 대답은 간단 sort보다는order
— 프라 사드 Chalasani

@Gavin-아마도 Prasad의 원래 코드를 오해했을 것입니다 (테스트 할 기계에 R이 없습니다 ...).하지만 주파수에 따라 카테고리를 재정렬하는 것처럼 보였습니다 reorder. 나는 더 많은 관련이 필요하다는이 질문에 동의합니다. 혼란을 드려 죄송합니다.
— 체이스

17

@HolgerBrandl에 의해 언급 된 forcats :: fct_infreq 외에도, forcats :: fct_rev가 있는데, 이는 인자 순서를 역전시킵니다.

theTable <- data.frame(
    Position= 
        c("Zoalkeeper", "Zoalkeeper", "Defense",
          "Defense", "Defense", "Striker"),
    Name=c("James", "Frank","Jean",
           "Steve","John", "Tim"))

p1 <- ggplot(theTable, aes(x = Position)) + geom_bar()
p2 <- ggplot(theTable, aes(x = fct_infreq(Position))) + geom_bar()
p3 <- ggplot(theTable, aes(x = fct_rev(fct_infreq(Position)))) + geom_bar()

gridExtra::grid.arrange(p1, p2, p3, nrow=3)             

gplot 출력


"fct_infreq (Position)"은 정말 감사합니다!
— Paul

12

나는 dplyr 내에서 계산하는 것이 최선의 해결책이라는 것을 zach에 동의합니다. 나는 이것이 가장 짧은 버전이라는 것을 알았다.

dplyr::count(theTable, Position) %>%
          arrange(-n) %>%
          mutate(Position = factor(Position, Position)) %>%
          ggplot(aes(x=Position, y=n)) + geom_bar(stat="identity")

이것은 계수가 ggplot이 아니거나를 사용하여 dplyr에서 수행되므로 계수 수준을 미리 재정렬하는 것보다 훨씬 빠릅니다 table.


12

아래 데이터 프레임에서와 같이 차트 열이 숫자 변수에서 나온 경우 더 간단한 솔루션을 사용할 수 있습니다.

ggplot(df, aes(x = reorder(Colors, -Qty, sum), y = Qty)) 
+ geom_bar(stat = "identity")  

정렬 변수 앞의 빼기 ​​부호 (-Qty)는 정렬 방향을 제어합니다 (오름차순 / 내림차순)

테스트 할 데이터는 다음과 같습니다.

df <- data.frame(Colors = c("Green","Yellow","Blue","Red","Yellow","Blue"),  
                 Qty = c(7,4,5,1,3,6)
                )

**Sample data:**
  Colors Qty
1  Green   7
2 Yellow   4
3   Blue   5
4    Red   1
5 Yellow   3
6   Blue   6

이 스레드를 찾았을 때 그것은 내가 찾던 대답이었습니다. 다른 사람들에게 유용하기를 바랍니다.


8

요인의 수준을 정렬 하기 위해 재정렬 을 사용하는 또 다른 대안 . 카운트에 따라 오름차순 (n) 또는 내림차순 (-n)으로 패키지 fct_reorder에서 사용하는 것과 매우 유사 forcats합니다.

내림차순

df %>%
  count(Position) %>%
  ggplot(aes(x = reorder(Position, -n), y = n)) +
  geom_bar(stat = 'identity') +
  xlab("Position")

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

오름차순

df %>%
  count(Position) %>%
  ggplot(aes(x = reorder(Position, n), y = n)) +
  geom_bar(stat = 'identity') +
  xlab("Position")

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

데이터 프레임 :

df <- structure(list(Position = structure(c(3L, 3L, 1L, 1L, 1L, 2L), .Label = c("Defense", 
"Striker", "Zoalkeeper"), class = "factor"), Name = structure(c(2L, 
1L, 3L, 5L, 4L, 6L), .Label = c("Frank", "James", "Jean", "John", 
"Steve", "Tim"), class = "factor")), class = "data.frame", row.names = c(NA, 
-6L))

5

우리는 단지의 분배를보고 있기 때문에 하나의 변수 들 사이의 관계를 찾고 반대 ( "위치") 두 변수 다음 아마도 히스토그램 보다 적절한 그래프 것이다. ggplot에는 geom_histogram () 이있어 쉽게 만들 수 있습니다 :

ggplot(theTable, aes(x = Position)) + geom_histogram(stat="count")

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

geom_histogram () 사용 :

내 생각 geom_histogram이 ( 가 다르게 연속 및 이산 데이터를 처리로) 조금 황당하다.

대한 지속적인 데이터 , 당신은 사용할 수 있습니다 geom_histogram () 매개 변수없이합니다. 예를 들어 숫자 벡터 "Score"를 추가하면 ...

    Name   Position   Score  
1   James  Goalkeeper 10
2   Frank  Goalkeeper 20
3   Jean   Defense    10
4   Steve  Defense    10
5   John   Defense    20
6   Tim    Striker    50

"Score"변수에서 geom_histogram ()을 사용하십시오.

ggplot(theTable, aes(x = Score)) + geom_histogram()

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

들면 개별 데이터 "위치"등 우리가 사용 된 바의 높이에 대한 y 값을주고 심미적으로 계산 된 통계치 계산을 지정할 필요 stat = "count":

 ggplot(theTable, aes(x = Position)) + geom_histogram(stat = "count")

참고 : 흥미롭고 혼란스럽게도 stat = "count"연속 데이터 에도 사용할 수 있으며 더 미학적으로 즐거운 그래프를 제공한다고 생각합니다.

ggplot(theTable, aes(x = Score)) + geom_histogram(stat = "count")

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

편집 : DebanjanB 의 유용한 제안 에 대한 답변이 확장되었습니다 .


0

나는 이것에 ggplot2대한 '자동'솔루션을 제공하지 않는 것이 매우 성가신 것을 발견했습니다 . 그래서에 bar_chart()함수를 만들었습니다 ggcharts.

ggcharts::bar_chart(theTable, Position)

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

기본적으로 bar_chart()막대를 정렬하고 가로 플롯을 표시합니다. 해당 세트를 변경하려면 horizontal = FALSE. 또한 bar_chart()막대와 축 사이의보기 흉한 '간극'을 제거합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.