0

在使用带有日期变量的数据框时,我遇到了 ggplot2 faceting 和 dplyr group_by 的错误。仅当我首先转换日期变量然后融化数据框时才会发生此错误。如果我做相反的事情,变量看起来完全一样,但不会出错。一个例子:

#base df
df <- data.frame(
id = c("A", "B", "C"),
date1 = c("12/Sep/2010", "13/Mar/2011", "05/Jan/2010"),
date2 = c("13/Sep/2010", "14/Mar/2011", "06/Jan/2010"),
value1 = 1:3,
value2 = 4:6
)

df
id       date1       date2 value1 value2
1  A 12/Sep/2010 13/Sep/2010      1      4
2  B 13/Mar/2011 14/Mar/2011      2      5
3  C 05/Jan/2010 06/Jan/2010      3      6

我将展示带有 mutate 的示例,但使用 df$date <- as.Date(df$date) 会给出相同的错误。我很抱歉,或者整理我的数据的丑陋和低效的代码(建议赞赏:-))。

#mutate first
df_muta <- df %>% mutate_each(funs(as.Date(., format = "%d/%b/%Y")), c(starts_with("date")))
df_muta <- data.frame(
  id = melt(df_muta, id.vars = c("id"), measure.vars = c("date1", "date2"))[[1]],
  date = melt(df_muta, id.vars = c("id"), measure.vars = c("date1", "date2"))[[3]],
  value = melt(df_muta, id.vars = c("id"), measure.vars = c("value1", "value2"))[[3]])

str(df_muta)
'data.frame':  6 obs. of  3 variables:
  $ id   : Factor w/ 3 levels "A","B","C": 1 2 3 1 2 3
  $ date : Date, format: "2010-09-12" "2011-03-13" "2010-01-05" ...
  $ value: int  1 2 3 4 5 6

p <- ggplot(df_muta, aes(x = date, y = value)) + geom_point()

我想发布剧情,但还没有 10 名声望。上面的单图没问题,日期在 x 轴上。如果我尝试刻面,x 轴将转换为数字。

p + facet_wrap( ~ id)

如果我尝试使用 dplyr group_by 它也会出错。

df_muta %>% group_by(id)
Error: column 'date' has unsupported type

所以我尝试先融化,然后转换日期。

df_melt <- data.frame(
  id = melt(df, id.vars = c("id"), measure.vars = c("date1", "date2"))[[1]],
  date = melt(df, id.vars = c("id"), measure.vars = c("date1", "date2"))[[3]],
  value = melt(df, id.vars = c("id"), measure.vars = c("value1", "value2"))[[3]])
df_melt <- df_melt %>% mutate(date = as.Date(date, format = "%d/%b/%Y"))

str(df_melt)
'data.frame':  6 obs. of  3 variables:
  $ id   : Factor w/ 3 levels "A","B","C": 1 2 3 1 2 3
  $ date : Date, format: "2010-09-12" "2011-03-13" "2010-01-05" ...
  $ value: int  1 2 3 4 5 6

两个数据框的结构和值似乎完全相同,但最后一个不会对分面图轴或 group_by 产生任何错误。它是一个错误吗?日期对象之间的区别在哪里?

谢谢!

4

1 回答 1

2

我认为这就是正在发生的事情。

df_muta <- df %>% mutate_each(funs(as.Date(., format = "%d/%b/%Y")), c(starts_with("date")))

#> df_muta
#  id      date1      date2 value1 value2
#1  A 2010-09-12 2010-09-13      1      4
#2  B 2011-03-13 2011-03-14      2      5
#3  C 2010-01-05 2010-01-06      3      6

#> df_muta$date1
#[1] "2010-09-12" "2011-03-13" "2010-01-05"

#> unclass(df_muta$date1)
#[1] 14864 15046 14614

在这里你可以看到日期。

df_muta <- data.frame(
    id = melt(df_muta, id.vars = c("id"), measure.vars = c("date1", "date2"))[[1]],
    date = melt(df_muta, id.vars = c("id"), measure.vars = c("date1", "date2"))[[3]],
    value = melt(df_muta, id.vars = c("id"), measure.vars = c("value1", "value2"))[[3]])

我跑了date = melt(df_muta, id.vars = c("id"), measure.vars = c("date1", "date2"))[[3]],看看 R 返回什么。这是结果。

#> date = melt(df_muta, id.vars = c("id"), measure.vars = c("date1", "date2"))[[3]]
#> date
#[1] 14864 15046 14614 14865 15047 14615
#attr(,"class")
#[1] "Date"

#> unclass(date)
#[1] 14864 15046 14614 14865 15047 14615
#attr(,"class")
#[1] "Date"

Class 仍然是 Date,但您会看到数字。现在让我以另一种方式排列数据。我在这篇文章中使用了原始 df。但是,我没有melt()在这里使用。

df$date1 <- as.Date(df$date1,format = "%d/%b/%Y")
df$date2 <- as.Date(df$date2,format = "%d/%b/%Y")

id <- rep(c("A", "B", "C"), each = 1, times = 2)
dates <- c(df$date1, df$date2)
values <-c(df$value1, df$value2)

foo <- data.frame(id, dates, values)

然后,我检查了 foo$dates

#> foo$dates
#[1] "2010-09-12" "2011-03-13" "2010-01-05" "2010-09-13" "2011-03-14" "2010-01-06"

#> unclass(foo$dates)
#[1] 14864 15046 14614 14865 15047 14615

我在这里有约会。

当您使用 df_muta 绘制 ggplot 时,您可以以某种方式绘制单个图形,尽管 df_muta$date 并不是真正的日期。但是,当您添加时facet_wrap,您的 df_muta$date 不适用于 ggplot。这是因为 ggplot 不认为你有约会。它认为你有数字。

如果我使用 foo,我可以毫无问题地执行以下操作。

p <- ggplot(foo, aes(x = dates, y = values)) + 
         geom_point() +
         facet_wrap( ~ id)

p

现在还有一个问题,与您的 df_melt 有关。当我运行你的脚本时,我收到了错误消息。

#> df_melt <- data.frame(
#+   id = melt(df, id.vars = c("id"), measure.vars = c("date1", "date2"))[[1]],
#+   date = melt(df, id.vars = c("id"), measure.vars = c("date1", "date2"))[[3]],
#+   value = melt(df, id.vars = c("id"), measure.vars = c("value1", "value2"))[[3]])
#Warning messages:
#1: attributes are not identical across measure variables; they will be dropped 
#2: attributes are not identical across measure variables; they will be dropped 
#> df_melt <- df_melt %>% mutate(date = as.Date(date, format = "%d/%b/%Y"))

同样,我在第一个 df_melt 中专注于您的日期部分

#> date = melt(df, id.vars = c("id"), measure.vars = c("date1", "date2"))[[3]]
#Warning message:
#attributes are not identical across measure variables; they will be dropped 

但是,当我检查第二个 df_melt 时,R 返回了以下内容。

#> df_melt$date
#[1] "2010-09-12" "2011-03-13" "2010-01-05" "2010-09-13" "2011-03-14" "2010-01-06"

#> unclass(df_melt$date)
#[1] 14864 15046 14614 14865 15047 14615

您在 df_melt$date 中有日期,而在 df_muta$date 中有数字作为日期。这些数字应该出现在 unclass 中。我不确定为什么会这样。我会推荐的一件事是你可能不想以你使用的方式使用融化。您会看到 R 将日期更改为 df_muta 中的数字。同样,您会在 df_melt 中看到 R 重新返回警告。简而言之,我相信你使用的方式melt()给了你有趣的结果。希望本次调查对您有所帮助。

于 2014-08-29T02:38:06.647 回答