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.