【问题标题】:Density plot based on time of the day基于一天中时间的密度图
【发布时间】:2018-01-23 17:39:24
【问题描述】:

我有以下数据集:

https://app.box.com/s/au58xaw60r1hyeek5cua6q20byumgvmj

我想根据一天中的时间创建一个密度图。这是我到目前为止所做的:

library("ggplot2")
library("scales")
library("lubridate")

timestamp_df$timestamp_time <- format(ymd_hms(hn_tweets$timestamp), "%H:%M:%S")

ggplot(timestamp_df, aes(timestamp_time)) + 
       geom_density(aes(fill = ..count..)) +
       scale_x_datetime(breaks = date_breaks("2 hours"),labels=date_format("%H:%M"))

它给出了以下错误: Error: Invalid input: time_trans works with objects of class POSIXct only

如果我将其转换为 POSIXct,它会将日期添加到数据中。

更新 1

以下转换数据为'NA'

timestamp_df$timestamp_time <- as.POSIXct(timestamp_df$timestamp_time, format = "%H:%M%:%S", tz = "UTC"

更新 2

以下是我想要实现的目标:

【问题讨论】:

  • timestamp_time 是一流的...character?您必须使用as.POSIXctas.POSIXlt 强制它。
  • timestamp_df$timestamp_time &lt;- as.POSIXct(timestamp_df$timestamp_time, format = "%H:%M%:%S", tz = "UTC") 将数据设为“NA”
  • 您的format 参数不正确。下次,您可以考虑为您的问题提供一个可重现的示例。

标签: r ggplot2 lubridate density-plot


【解决方案1】:

这是一种方法:

library(ggplot2)
library(lubridate)
library(scales)

df <- read.csv("data.csv") #given in OP

将字符转换为POSIXct

df$timestamp <- as.POSIXct(strptime(df$timestamp, "%m/%d/%Y %H:%M",  tz = "UTC"))

library(hms)

提取小时和分钟:

df$time <- hms::hms(second(df$timestamp), minute(df$timestamp), hour(df$timestamp))  

再次转换为POSIXct,因为ggplot 不适用于hms 类。

df$time <- as.POSIXct(df$time)


ggplot(df, aes(time)) + 
  geom_density(fill = "red", alpha = 0.5) + #also play with adjust such as adjust = 0.5
  scale_x_datetime(breaks = date_breaks("2 hours"), labels=date_format("%H:%M"))

将其绘制为 1:

ggplot(df) + 
  geom_density( aes(x = time, y = ..scaled..), fill = "red", alpha = 0.5) +
  scale_x_datetime(breaks = date_breaks("2 hours"), labels=date_format("%H:%M"))

其中..scaled.. 是在绘图创建期间生成的stat_density 的计算变量。

【讨论】:

  • 非常感谢!我正在尝试以“2 小时”休息格式制作这个情节,而不是日期。基本上我想看看 24 小时内的计数在什么时候高。有社交帖子的时间戳。
  • 对不起;也许,我并不完全清楚想要什么。我已经更新了原帖。
  • 太棒了!我能够根据您的解决方案重新创建它。一个问题 - 为什么它在 y 轴上显示科学数字?我通过使用options(scipen=10000) 更改了它,所以它现在显示十进制数字。我应该从十进制解释什么?
  • 密度曲线在任何地方都必须是非负的,并且整条曲线的积分必须等于 1。如果你愿意,你也可以按比例绘制它:检查编辑。
【解决方案2】:

此处发布的解决方案的一个问题是它们忽略了此数据是圆形/极性的事实(即 00hrs == 24hrs)。您可以在另一个答案的图表上看到图表的末端彼此不匹配。这不会对这个特定的数据集产生太大的影响,但对于发生在午夜附近的事件,这可能是一个极其有偏差的密度估计。考虑到时间数据的循环性质,这是我的解决方案:

# modified code from https://freakonometrics.hypotheses.org/2239

library(dplyr)
library(ggplot2)
library(lubridate)
library(circular)

df = read.csv("data.csv")
datetimes = df$timestamp %>%
  lubridate::parse_date_time("%m/%d/%Y %h:%M")
times_in_decimal = lubridate::hour(datetimes) + lubridate::minute(datetimes) / 60
times_in_radians = 2 * pi * (times_in_decimal / 24)

# Doing this just for bandwidth estimation:
basic_dens = density(times_in_radians, from = 0, to = 2 * pi)

res = circular::density.circular(circular::circular(times_in_radians,
                                                    type = "angle",
                                                    units = "radians",
                                                    rotation = "clock"),
                                 kernel = "wrappednormal",
                                 bw = basic_dens$bw)

time_pdf = data.frame(time = as.numeric(24 * (2 * pi + res$x) / (2 * pi)), # Convert from radians back to 24h clock
                      likelihood = res$y)

p = ggplot(time_pdf) +
  geom_area(aes(x = time, y = likelihood), fill = "#619CFF") +
  scale_x_continuous("Hour of Day", labels = 0:24, breaks = 0:24) +
  scale_y_continuous("Likelihood of Call") +
  theme_classic()

请注意,密度图的值和斜率在 00h 和 24h 点匹配。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-08-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-19
    • 2015-02-22
    • 2012-09-23
    相关资源
    最近更新 更多