xyplot
API获得的csv数据中提取一个RescueTime
,用于“ http://codereview.stackexchange.com”的活动时间。# -------------------------------------------------------
# PLOT TIME SPENT ON CODEREVIEW SE
# USING RESCUE TIME API AND R
# -------------------------------------------------------
# -------------------------------------------------------
# LIBRARIES
if(!require("RCurl")){
install.packages("RCurl")
}
if(!require("lattice")){
install.packages("lattice")
}
require("RCurl")
require("lattice")
# -------------------------------------------------------
print("Initializing...")
# -------------------------------------------------------
# RESCUE TIME API ACCESS
# api key
# get from https://www.rescuetime.com/anapi/manage
api_key <- "..."
# query from date
from_date <- "2014-01-01"
# query to date
to_date <- format(Sys.Date(), "%Y-%m-%d")
# activity to get details of
activity <- "codereview.stackexchange.com"
# --api description--
# for more details see https://www.rescuetime.com/anapi/setup/documentation
# key - API key
# format - Output format
# rb - Restrict Start Date ("%Y-%m-%d")
# re - Restrict End Date ("%Y-%m-%d")
# rk - Restrict Kind (in this case it's activity)
# pv - Perspective (in this case it's interval)
# rs - Resolution Time (if it is day it's a daily report)
# rt - Restrict Thingy (Restrict Kind of Type)
url_format <- "https://www.rescuetime.com/anapi/data?key=%s&format=csv&rb=%s&re=%s&rk=activity&pv=interval&rs=day&rt=%s"
# create url
api_url <- sprintf(url_format,api_key,from_date,to_date,activity)
# -------------------------------------------------------
# -------------------------------------------------------
# PLOT
# get csv as a text
csv_text_data <- textConnection(getURL(api_url))
# parse csv
activity_data <- read.csv(csv_text_data,header = TRUE)
print(sprintf("Mean Time Spent on '%s':%f (seconds)",activity,mean(activity_data$Time)))
activity_time_spent <- activity_data$Time
activity_dates <- activity_data$Date
# create an index for dates
activity_date_index <- 1:length(activity_dates)
# plot
print(xyplot(activity_time_spent ~ activity_date_index, type="b", xlab = "Date Index", ylab = "Time (seconds)" ))
# -------------------------------------------------------
# -------------------------------------------------------
# CLEAN UP
detach("package:RCurl", unload = TRUE)
detach("package:lattice", unload = TRUE)
rm(list = ls())
# -------------------------------------------------------
这是否遵循R约定?
通过使用
source("./codereview.R")
将其加载到R控制台中来执行下载
CSV和R文件
输出
Loading required package: RCurl Loading required package: bitops Loading required package: lattice [1] "Initializing..." [1] "Mean Time Spent on 'codereview.stackexchange.com':2764.559322 (seconds)"
#1 楼
这是我将重写您的代码的方法。我将在以下内容添加我的评论:plotActivity <- function(
activity = 'codereview.stackexchange.com',
api_key = getOption('rescuetime_api_key'),
from_date = NULL,
to_date = NULL) {
## This function plots time spent on a given URL
## using the rescue time API
##
## Arguments:
## - activity: the url you want to check for usage
## - api_key: user API key, you can get yours at
## https://www.rescuetime.com/anapi/manage
## - from_date: a Date or string in "YYYY-MM-DD" format,
## defaults to January 1st of the same year as to_date
## - to_date: a Date or string in "YYYY-MM-DD" format,
## defaults to today
## - verbose: adds verbose, defaults to FALSE
library("RCurl")
library("ggplot2")
# arguments parsing and default settings
if (is.null(api_key)) stop("please set your rescue time API key...")
if (is.null(to_date)) to_date <- Sys.Date()
to_date <- as.Date(to_date)
if (is.na(to_date)) stop("error parsing to_date...")
if (is.null(from_date)) from_date <- format(to_date, "%Y-01-01")
from_date <- as.Date(from_date)
if (is.na(from_date)) stop("error parsing from_date...")
# build the API request url
# for more details see https://www.rescuetime.com/anapi/setup/documentation
base_url <- "https://www.rescuetime.com/anapi/data"
arguments <- c(key = api_key, # API key
format = 'csv', # Output format
rb = from_date, # Restrict Start Date
re = end_date, # Restrict End Date
rk = 'activity', # Restrict Kind
pv = 'interval', # Perspective
rs = 'day', # Resolution Time
rt = activity) # Restrict Thingy (Restrict Kind of Type)
arg_str <- paste(names(arguments), arguments, sep = '=', collapse = '&')
api_url <- sprintf("%s?%s", base_url, arg_str)
# read data
csv_text_data <- textConnection(getURL(api_url))
activity_data <- read.csv(csv_text_data, header = TRUE)
# print diagnostic and plot
cat(sprintf("Total Time Spent between %s and %s on '%s':%f (seconds)",
activity, from_date, end_date, sum(activity_data$Time)))
activity_data$Date <- as.Date(activity_data$Date)
ggplot(activity_data, aes(x=Date, y=Time.Spent..seconds.)) +
geom_bar(stat="identity") +
xlab("Date") +
ylab("Time (seconds)")
}
所以这里有一些想法:
我从脚本转到了功能。这样,使用和共享变得容易得多。我已经抽象出了我认为所有正确的输入和合理的默认值。有趣的是
getOption
使用了api_key
,因此用户可以通过运行options(rescuetime_api_key = "xyz123abc")
一次对其进行一次设置。所以现在,您要做的就是从将要存储此函数的文件中获取源代码,然后调用该函数。函数在执行时会在自己的环境中运行,因此在退出函数时,会删除运行时创建的所有变量。您的全局环境永远不会受到污染,这消除了对您的“清理”部分的需要(如janos所指出的那样,这是非常有害的。)像
rm(list=ls())
一样,强制通过install.packages()
安装软件包有点有害。不,您只想使用library
,它将立即在那里消失,使用户可以决定安装软件包。有一个不错的博客,介绍为什么有些人-包括我-喜欢library
而不是require
:http://yihui.name/en/2014/07/library-vs-require 无论我在哪里使用R的Date对象
我重写了api url的构建方式,并使用了命名向量作为参数。带有内联注释。希望您会同意该代码更具可读性和易于维护性,这是您应始终追求的目标。
我将
print
替换为cat
。这样,您就不会获得打印矢量时附带的[1]
前缀。这与代码审阅没有多大关系,但我认为查看网站上的总时间会更有用。每天的平均时间可能有点令人困惑:用户可能想知道,是包括整天还是仅包含访问网站的那一天(您选择了后者)。而总时间消除了这种歧义。另外,我认为将数据绘制为具有实时刻度的条形图会更有用,即在不访问该网站的期间包含空洞。我用的是
ggplot2
,请参见下图。 x轴可能看起来很奇怪,但是您确实在7月1日花了六秒钟在网站上,所以这就是它从那天开始的原因,尽管您不会真正注意到那里有数据点。我的改写摆脱了
activity_date_index <- 1:length(activity_dates)
,但是如果我需要它,我会使用activity_date_index <- seq_along(activity_dates)
。像seq_len
或seq_along
这样的函数比1:n
更好的实践,因为当n
为零时,它们可以正确处理特殊情况。他们返回一个空向量(c()
),而1:n
将返回向量c(1, 0)
并造成破坏。免责声明:我没有该抢救时间网站的帐户,所以我无法完全测试我的代码。如果发现错误,请随时编辑我的帖子,我不在乎。
感谢您共享代码,我喜欢R,特别喜欢看到人们使用它来连接和分析在线数据库。就像你在这里一样。希望我的评论对您有所帮助。
评论
\ $ \ begingroup \ $
好的答案,请参加第二聊天室。我们需要更多的R人。
\ $ \ endgroup \ $
–bhathiya-perera
14-10-1在6:02
#2 楼
不错的倡议!而且R对于这类东西是完美的。条件逻辑
if(!require("lattice")){
install.packages("lattice")
}
require("lattice")
如果第一个
require
是成功,则无需再次调用。您可以在if
内部移动第二个:if(!require("lattice")){
install.packages("lattice")
require("lattice")
}
编码样式
对于编码样式,您可能会发现Google的R样式指南很有趣。 br />
如果阅读过多,请注意,其他语言中的许多常规建议也对R有意义。
示例#1:在参数列表中的逗号后加空格:
if语句中打开括号和关闭括号之前放置一个空格:
# not so good
api_url <- sprintf(url_format,api_key,from_date,to_date,activity)
# better
api_url <- sprintf(url_format, api_key, from_date, to_date, activity)
依此类推。
清理
我敢肯定最后清理的目的是最好的。
这可能是有害的。
/>
如果在运行脚本之前已经加载了
RCurl
和lattice
库,又希望在之后加载它们呢?这可能是完全有害的:
# not so good
if(!require("RCurl")){
# better
if (!require("RCurl")) {
这将删除全局名称空间中的所有对象。
如果您在runni之前有重要的内容在此脚本中,
它会丢失。
我看到的清除代码的唯一用途是,如果在运行该脚本后,您想继续在一个干净的会话中工作。
但是,退出并重新启动会容易得多。
未来的代码回顾
下载链接中包含的CSV文件包含59行。
还不错,您可以将它逐字地包含在问题中。
我没有使用真实的API进行测试,
检索到的方法没有太多测试仍然是URL。
我只是将代码更改为如下所示:
rm(list = ls())
评论
\ $ \ begingroup \ $
print(xyplot(...))在脚本中是必需的,它返回格状图对象;参见R FAQ 7.22
\ $ \ endgroup \ $
–rcs
14-10-16在7:26
\ $ \ begingroup \ $
真的吗?好了,将其删除,感谢您的指出!
\ $ \ endgroup \ $
– janos
14-10-16在7:27
评论
相关Meta:meta.codereview.stackexchange.com/questions/2521/…