对字符类数据框列和图重新排序

时间:2018-12-17 08:24:01

标签: r ggplot2

我有一个如下数据框:

df <- data.frame(date.time = c("Fri 00:00", "Fri 23:30", "Mon 00:00", "Mon 23:30", 
                               "Sat 00:00", "Sat 23:30", "Sun 00:00", "Sun 23:30", 
                               "Thu 00:00", "Thu 23:30", "Tue 00:00", "Tue 23:30", 
                               "Wed 00:00", "Wed 23:30"), 
                 Price = c(36.15368, 41.61206, 30.80412, 37.47360, 38.04516, 35.72798, 
                           33.05613, 32.65447, 35.50335, 41.81241, 35.14006, 37.56432, 
                           35.04553, 38.00721))

date.time值为类字符,而Price值为类数字。我想使用ggplot绘制数据。问题在于数据顺序错误。我想要以下命令:sun, mon, ..., sat

我尝试使用以下代码执行此操作:

my.order <- c(7,8,3,4,11,12,13,14,9,10,1,2,5,6)
df %>% 
  ggplot(aes(x = reorder(date.time, my.order), y = Price, group = 1)) + 
  geom_line()

但是我最终得到一个奇怪的命令,该命令从原始数据帧的“ Tue”行开始。我在做什么错了?

我也想标记x轴,所以我尝试了以下代码:

df %>% 
  ggplot(aes(x = reorder(date.time, my.order), y = Price, group = 1)) + 
  geom_line() + 
  scale_x_discrete(name = 'Day', breaks = df$date.time[c(1,3,5,7,9,11,13)], 
                   labels = c("Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"))

但是标签以原始数据集的顺序结束,而该图如上所述从“ Tue”开始排序。如何使数据和标签以我想要的顺序显示?

编辑:我认为这可能与关卡有关。运行以下代码

df$date.time[c(7,8,3,4,11,12,13,14,9,10,1,2,5,6)]

产生以下输出

[1] Sun 00:00 Sun 23:30 Mon 00:00 Mon 23:30 Tue 00:00 Tue 23:30 Wed 00:00 Wed 23:30
[9] Thu 00:00 Thu 23:30 Fri 00:00 Fri 23:30 Sat 00:00 Sat 23:30
14 Levels: Tue 00:00 Tue 23:30 Mon 00:00 Mon 23:30 Wed 00:00 Wed 23:30 ... Sun 23:30

不确定为什么。

2 个答案:

答案 0 :(得分:2)

您的代码实际上完成了您在问题的第一部分中要执行的操作:尊重df中数据的顺序,您将位置12分配给了两个Tue值,这就是ggplot2首先绘制它们的原因。

运行以下命令时,您可以看到与每个元素关联的数字:

my.order <- c(7,8,3,4,11,12,13,14,9,10,1,2,5,6)
reorder(df$date.time, my.order)

您可以将此向量用于my.order

my.order <- c(11,12,3,4,13,14,1,2,9,10,5,6,7,8)
df %>% 
  ggplot(aes(x = reorder(date.time, my.order), y = Price, group = 1)) + 
  geom_line()

与方法df$date.time[c(7,8,3,4,11,12,13,14,9,10,1,2,5,6)]的不同之处在于,在您的第一种重新排序方法中,您将位置关联到向量的每个元素(即第一个元素的位置为7,第二个元素的位置为8等),而在方括号方法中,您定义向量中元素出现的顺序(即,第7个元素排在第1位,第8个元素排在第2位,依此类推)。

您会发现在ggplot调用中使用方括号方法无济于事,因为ggplot2默认情况下会自动使用字母顺序,即,数据框中数据的顺序无关紧要(数据为字符串或因子不会产生任何影响)。

但是,如果您使用因子(这是使用data.frame()函数存储字符串时的默认值),则可以排序其级别

df$date.time <- ordered(df$date.time,
                        levels = df$date.time[c(7,8,3,4,11,12,13,14,9,10,1,2,5,6)])
# see the new ordered levels
levels(df$date.time)
# visualise as is, ggplot2 uses ordered levels
df %>% 
  ggplot(aes(x = date.time, y = Price, group = 1)) + 
  geom_line()

对于标签,由于级别的顺序未更改数据在数据框中的顺序,因此您仍然必须参考其原始位置。但是,如果您希望原始代码能够正常工作,则可以根据订购的级别添加步骤以重组整个数据框:

library(dplyr)
df <- df %>% 
  arrange(date.time)

dplyr::arrange()函数将考虑排序的级别,并且现在按预期对行进行排序。

您原来的标签方法应该可以正常工作

df %>% 
  ggplot(aes(x = date.time, y = Price, group = 1)) + 
  geom_line() +
  scale_x_discrete(name = 'Day', breaks = df$date.time[c(1,3,5,7,9,11,13)],
                   labels = c("Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"))

答案 1 :(得分:1)

要让星期日首先出现,请执行以下操作:

 df$date.time <- reorder(df$date.time, my.order)
 df %>% 
   ggplot(aes(x = as.character(date.time), y = Price, group = 1)) + 
   geom_line()

不知道为什么,但是将其设置为字符可以解决重新排序问题。

编辑:使用as.character()似乎标签也可以使用?

 df %>% 
  ggplot(aes(x = as.character(date.time), y = Price, group = 1)) + 
  geom_line() + 
  scale_x_discrete(name = 'Day', breaks = df$date.time[c(1,3,5,7,9,11,13)], 
                   labels = c("Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"))