Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement new coord_mirror() and theme_rtl() for RtL plotting #2817

Closed
wants to merge 7 commits into from

Conversation

@dpseidel
Copy link
Member

@dpseidel dpseidel commented Aug 9, 2018

This PR is a WIP. Inspired by this article, I have begun playing around with how to implement RtL plotting in ggplot2. Though there seems to be some debate about what is a correct implementation of RtL axes and it seems many RtL languages plot LtR anyhow, I think the functionality is really neat and ggplot2 should consider adding features that make it possible for the audiences that would use it. In that vein....

Currently this implementation was really quite simple. I simply adapted coord_flip() to create a new coord_mirror() and then added a new theme_rtl(). This doesn't yet deal with the text encoding issue mentioned in the original article but as they note much of that is OS specific so possibly/probably outside the scope of ggplot2.

As currently implemented, a RtL plot requires 3 specifications: the new theme, the new coord, and (at least for continuous data) scale_x_reverse(). I wonder if there is a better way to go about this or a way to bundle these three elements together in some sort of default. Example below:

library(ggplot2)
library(tibble)
df <- tibble(x = 1:10, y = 1:10, z = rep(c("A", "B"), 5))
ggplot(df, aes(x, y, col = z)) + 
  geom_point() + 
  coord_mirror() + 
  theme_rtl() + 
  scale_x_reverse() +
  ggtitle("Right Aligned Title")

df2 <- tibble(x = letters[1:10], y = 1:10, z = rep(c("A", "B"), 5))
ggplot(df2, aes(x, y, col = z)) + 
  geom_point() + 
  coord_mirror() + 
  theme_rtl() +
  ggtitle("Right Aligned Title")

@isteves has been super helpful in thinking about this, and may have some opinions to add to any discussion or iteration so I'm tagging her here.

dpseidel and others added 2 commits Jul 18, 2018
Dana Paige Seidel
@clauswilke
Copy link
Member

@clauswilke clauswilke commented Aug 9, 2018

I would expect a coord_mirror() to reverse the x axis.

@dpseidel
Copy link
Member Author

@dpseidel dpseidel commented Aug 9, 2018

@clauswilke certainly it could be implemented that way. The plot I was original trying to replicate, from the article linked above, did not flip the x axis (they were plotting a discrete variable) which is why I left it the way I did, but you're right that's an easier implementation.

@clauswilke
Copy link
Member

@clauswilke clauswilke commented Aug 9, 2018

I think all you need to do is add the following function to your CoordMirror():

  setup_panel_params = function(self, scale_x, scale_y, params = list()) {
    params <- ggproto_parent(CoordCartesian, self)$setup_panel_params(scale_x, scale_y, params)
    
    params$x.range <- rev(params$x.range)
    params$x.labels <- rev(params$x.labels)
    params
  }

And it seems to work with discrete and continuous scales. I would assume in right-to-left writing the first letter in the alphabet is shown in the right-most position, which this addition to the coord achieves.

@dpseidel
Copy link
Member Author

@dpseidel dpseidel commented Aug 9, 2018

Great! Thanks for the quick code @clauswilke! It's implemented now and things actually mirror as you would expect without the scale_x_reverse() call.

library(ggplot2)
library(tibble)
df <- tibble(x = 1:10, y = 1:10, z = rep(c("A", "B"), 5))
ggplot(df, aes(x, y, col = z)) +
  geom_point() +
  coord_mirror() +
  theme_rtl() +
  ggtitle("Right Aligned Title")

df2 <- tibble(x = letters[1:10], y = 1:10, z = rep(c("A", "B"), 5))
ggplot(df2, aes(x, y, col = z)) +
  geom_point() +
  coord_mirror() +
  theme_rtl() +
  ggtitle("Right Aligned Title")

Created on 2018-08-09 by the reprex
package
(v0.2.0).

@clauswilke
Copy link
Member

@clauswilke clauswilke commented Aug 10, 2018

Another point: Maybe make theme_rtl() not a complete theme so it can be combined with other themes. I.e., something like:

theme_rtl <- function() {
  theme(
    legend.position = "left",
    plot.title = element_text(hjust = 1)
  )
}

(Maybe there's a better name for the function, though, so it sounds like a verb and not a noun. Maybe make_theme_rtl() or reverse_theme().)

@isteves
Copy link

@isteves isteves commented Aug 10, 2018

Hi all, I don't have anything technical to contribute to this discussion, but I'd like to summarize my investigation into RTL graphs here (@dpseidel has already heard much of this).

I'm of the camp that RTL graphs with continuous axes should not be encouraged. (In my mind, it's a bit like all agreeing to the metric system and then deciding to switch back into non-standard units.) Mathematics has a standard convention with regards to axes, and I think we should stick with it.

Conversations with people familiar with RTL languages

  • Iranian lady (psychology PhD) that I met in a hostel - graphs are always LTR, tables are RTL. Math is LTR
  • Pakistani taxi driver (Aamer) - both RTL/LTR are taught in schools, depending on which language (Urdu/English) is being used
  • Israeli friend 1: "I did it only once or twice. It is rare in papers that I saw."
  • Israeli friend 2: "I also hate RTL in this context, and changed it for my school pupils when they gave me such figures." (note: this is what Excel defaults to for RTL languages)
  • East Asian studies PhD: In China, writing is almost always LTR. In Taiwan, it's still mixed. You can get writing that is RTL/LTR/up-to-down, but typically horizontal writing is now LTR and vertical writing is RTL. Regardless, all graphs are LTR.

Online graph search

I found it surprisingly difficult to search for graphs in RTL languages, but I hit on a few methods that seem to work ok:

  • Google Image search "stock market" or "growth" or "statistics" - I used Google Translate to get words in Arabic/Hebrew/Persian/Urdu for my searches. The vast majority of the results seemed to be LTR.
  • Google Scholar search. I tried a similar tactic with Google scholar, but it was a bit more difficult because graphs are hidden in PDFs. *Note: the place of origin are educated guesses based on the URL but may be wrong
    • Iran: example 1 example 2
    • Iraq: example 1 example 2
    • Israel: Most of the papers that came up were locked behind JSTOR, so I didn't bother with them. My friend sent me newspaper photos instead (from Haaretz):

downloads

@adisarid
Copy link

@adisarid adisarid commented Dec 24, 2018

I'm with @isteves on this one. The mathematical convention of left to right usually remains even when the language is RTL (at least from my perspective as a native Hebrew speaker).

The only real thing that is truly needed in terms of RTL charts is not actually covered in this pull request. This is the direction of text. I.e., if you have punctuation marks in the text they will appear at the wrong side. hjust controls the text alignment but not the text direction. See the stackoverflow question I posted here.

@clauswilke
Copy link
Member

@clauswilke clauswilke commented Dec 24, 2018

@adisarid This is of interest to me, as I'm planning to improve text handling in ggplot2. How does right-to-left text usually work? Is it reasonable to assume that layouting works just like left-to-right only in the other direction, or are there additional issues? And what are the conventions for mixed text? It seems to get complicated pretty quickly.

@adisarid
Copy link

@adisarid adisarid commented Dec 25, 2018

@clauswilke - good question.
Apparently, my stackoverflow question, which is a simpler version to what you are asking, was answered, and it's not that complicated as I thought. All I needed was a unicode explicit directional embedding paste("\u202B", "זה טקסט בעברית!") and that tells the device to render the text RTL (see Henrik's answer). The ! would go in the right place (which is opposite to how this markdown is rendered).

To implement this in element_text, I guess the simplest thing would be to add a flag parameter which does this, i.e., element_text(directionRTL = TRUE), and then the element's text gets concatenated with this directional character.

For mixed text, e.g. English with Hebrew/Arabic. It's indeed more complicated, because you have to guess when an English word is meant to end a Hebrew sentence or start a new English sentence.
We would have to use a smart parser which goes over the original text and when it detects a Hebrew/Arabic character set it wraps it with \u202B and ends it with \u202A. These wrappers would have to include punctuation marks which end sentences (so characters like .?!- need to be interpreted either as English or as Hebrew/Arabic, depending on context). The decision about including or excluding English words within the unicode wrappers would have to be decided based on if that English word was preceded by a stop-sentence punctuation (i.e., !.?) would exclude the word from the RTL command, but not things like :- .

Makes sense?

@certara-smouksassi
Copy link

@certara-smouksassi certara-smouksassi commented Dec 25, 2018

One issue in these languages ( at least in arabic) is that you might have separate rules for numerals:
https://www.w3.org/TR/alreq/#h_numbers
https://www.vengaglobal.com/blog/bi-directional-languages-arabic-hebrew-farsi/

@thomasp85
Copy link
Member

@thomasp85 thomasp85 commented Apr 11, 2019

@dpseidel what is the status of this PR?

@dpseidel
Copy link
Member Author

@dpseidel dpseidel commented Apr 11, 2019

It's functional and pretty close to finished, just needs a few visual tests. I agree it could be nice to make it an incomplete theme as suggested by @clauswilke.

It begin as simple curiosity during my internship. Ultimately it stalled because it wasn't clear if there was consensus on exactly how and when RtL plotting is used in the wild and thus, how it should be it should be implemented in ggplot2, if at all. @hadley, what do you think? Is this a feature you'd still like to see in ggplot2?

If we decide it's worth considering further I'm happy to finish it off either in time for 3.2 or for a release down the road a bit.

@hadley
Copy link
Member

@hadley hadley commented Apr 11, 2019

I think it's worth finishing off by making it a partial theme, and removing the x-axis mirroring.

@dpseidel dpseidel changed the title (WIP) Implement new coord_mirror() and theme_rtl() for RtL plotting Implement new coord_mirror() and theme_rtl() for RtL plotting Apr 14, 2019
@dpseidel
Copy link
Member Author

@dpseidel dpseidel commented Apr 14, 2019

Alright, I have reverted the x-axis mirroring, converted theme_rtl to a partial theme, and added a visual test. Since it was no longer a complete theme, I gave it it's own documentation but left it in the theme-default.r file.

@dpseidel dpseidel requested a review from hadley Apr 14, 2019
@thomasp85
Copy link
Member

@thomasp85 thomasp85 commented Aug 13, 2020

We are closing this. It appears that only the titles should be right-aligned in an rtf theme which is so easy to change that the addition of a new theme seems overkill. Work on supporting correctly rendered non-western scripts (e.g. Arabic, Urdu, Hebraic) continues in ragg and textshaper

@thomasp85 thomasp85 closed this Aug 13, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked issues

Successfully merging this pull request may close these issues.

None yet

7 participants