ggplot2: display text labels from one group only

a 夏天 提交于 2021-02-07 08:13:57

问题


My setup:

I have a tibble of basketball players and their statistics.

library(tidyverse)

df <- tibble(
  season = c(2010, 2011, 2012, 2013, 2014,
             2010, 2011, 2012, 2013, 2014),
  player = c("player_a", "player_a", "player_a", "player_a", "player_a",
             "league_avg", "league_avg", "league_avg", "league_avg", "league_avg"),
  fg_perc = c(.4912, .6083, .3095, .5525, .4289,
              .4825, .4836, .4819, .4860, .4848),
  points_game = c(20, 18, 15, 19, 18,
                  12, 12, 13, 11, 12)
)

I've displayed a certain column (fg_perc) as a geom_line() for both player_a and league_avg. I've also wrapped it in a custom function, as I'll be using the same method for other statistics.

make_chart <- function(target_column) {
  df %>% 
    ggplot(aes_string("season", target_column, label = target_column)) + 
    geom_line(aes(color = player), size = 1.33)
}

make_chart("fg_perc")

My issue:

I want to display the fg_perc values as percentages for player_a data only. I can't figure out how to do this without eliminating the legend (when I spread() league_avg). I'm looking for a solution that will also be able to keep non-percentage numbers as-is, and display them in similar fashion (e.g. points_game for player_a only). The output would look something like this (please excuse the MS Paint):

Thanks!


回答1:


If you want to use your make_chart function without hardcoding, you'll want to use non-standard evaluation (nse). Many of the tidyverse functions have nse versions, indicated by a _ after the function name. You would use these versions if you're using them programmatically.

Below would be a rough example of using the nse versions of aes and filter, aes_ and filter_. There is a lot more to building functions using nse than what I've done here. I suggest you read the dplyr vignette on nse for more.

I simply replicated the solution @OmaymaS provided, with a filter_ rather than the ifelse. I also took the liberty of adding a data parameter .data to your function, along with a player_highlight parameter. The .data lets your function be pipeable and the player_highight lets you choose which player you want to highlight (as they'll probably be more than one). You'll most likely want to expand the functionality, and should do so!

library(tidyverse)

df <- data_frame(
  season = c(2010, 2011, 2012, 2013, 2014,
             2010, 2011, 2012, 2013, 2014),
  player = c("player_a", "player_a", "player_a", "player_a", "player_a",
             "league_avg", "league_avg", "league_avg", "league_avg", "league_avg"),
  fg_perc = c(.4912, .6083, .3095, .5525, .4289,
              .4825, .4836, .4819, .4860, .4848),
  points_game = c(20, 18, 15, 19, 18,
                  12, 12, 13, 11, 12)
)


make_chart <- function(.data, target_column, player_highlight) {
    ggplot(.data, aes_(x = ~season, y = as.name(target_column))) + 
    geom_line(aes_(color = ~player), size = 1.33) +
    geom_text(data = filter_(.data, ~ player == player_highlight), aes_(label = as.name(target_column)))
}

make_chart(df,"fg_perc","player_a")

df %>% 
  make_chart("fg_perc","player_a")



回答2:


Check this out: You can set your condition with ifelse inside geom_text:

  • if player==the player of interest, the label will be the % value

  • otherwise, the label will be empty " "

You can whatever condition you want, or multiple players.

df %>% 
        ggplot(aes(season,fg_perc))+
        geom_line(aes(color = player), size = 1.33)+
        geom_text(aes(label=ifelse(player=="player_a",paste0(100*fg_perc,"%")," ")))

EDIT

If you want to wrap the code in a function, you can use try the following, where you use aes_string inside geom_text to be able to pass the column name as a string.

In case all your target columns are percentages:

  • you can multiply the column by 100 in advance inside the function (or mutate before passing the df)

    make_chart <- function(target_column) {
    
        df[,target_column] <- 100*df[,target_column]
    
        df %>% 
                ggplot(aes_string("season", target_column)) + 
                geom_line(aes(color = player), size = 1.33) +
                geom_text(data=filter(df,player=="player_a"),
                          aes_string(label=target_column))+
                # a work around to add the % sign
                geom_text(data=filter(df,player=="player_a"),
                          aes(label="%"),
                          hjust=-1.5) }
    




回答3:


The trick here is to use the geom_label geometry with a tweaked label aesthetic:

df %>% ggplot(aes(season, fg_perc, color = player)) + 
    geom_line() + 
    geom_label(aes(label = ifelse(player == 'league_avg', NA, fg_perc)))

So now only for the label we set the fg_perc values to NA if the player is league_avg, this omits them from the plot.



来源:https://stackoverflow.com/questions/40658754/ggplot2-display-text-labels-from-one-group-only

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!