【问题标题】:How to split the timestamp in R for Googlevis for no overlap如何在 R 中为 Googlevis 拆分时间戳以防止重叠
【发布时间】:2015-08-17 15:18:19
【问题描述】:

所以我们收集的时间戳数据有 19 位。我们运行它的第一种方式,我们得到了这些不应该存在的重叠。我试图忽略前 10 位并尝试其余的,但我得到了错误。如何以没有重叠的方式显示它,并且只包含以分钟、秒、毫秒左右为单位的持续时间?因为所有这些实验几乎都在同一时间和同一日期发生,所以我不想显示冗余数据。

library('googleVis')
dd <- read.csv("output_2015-08-05-17-07-12_gaze.txt", header = TRUE, sep = ",",colClasses = c('character','character'))
dd <- within(dd, {
  end <- as.POSIXct(as.numeric(substr(rosbagTimestamp, 11, 14)) / 1e9,
                    origin = '1970-01-01')
  start <- as.POSIXct(as.numeric(substr(rosbagTimestamp, 14, 19)) / 1e9,
                      origin = '1970-01-01')
  rosbagTimestamp <- NULL
})

## sum the times by group
dd1 <- aggregate(. ~ data, data = dd, sum)
dd1 <- within(dd1, {
  start <- as.POSIXct(start, origin = '1970-01-01')
  end <- as.POSIXct(end, origin = '1970-01-01')
})


plot(gvisTimeline(dd1, rowlabel = 'data', barlabel = 'data',
                  start = 'start', end = 'end', options=list(width="600px", height="800px")))

还有一个显示小时并且有重叠的是这样的:

dd <- read.csv("output_2015-08-05-17-07-12_gaze.txt", header = TRUE, sep = ",",colClasses = c('character','character'))
dd <- within(dd, {
  end <- as.POSIXct(as.numeric(substr(rosbagTimestamp, 1, 10)) / 1e9,
                    origin = '1970-01-01')
  start <- as.POSIXct(as.numeric(substr(rosbagTimestamp, 11, 19)) / 1e9,
                      origin = '1970-01-01')
  rosbagTimestamp <- NULL
})

## sum the times by group
dd1 <- aggregate(. ~ data, data = dd, sum)
dd1 <- within(dd1, {
  start <- as.POSIXct(start, origin = '1970-01-01')
  end <- as.POSIXct(end, origin = '1970-01-01')
})
plot(gvisTimeline(dd1, rowlabel = 'data', barlabel = 'data',
                  start = 'start', end = 'end', options=list(width="600px", height="800px")))

这是link to dataset

【问题讨论】:

    标签: r plot charts google-visualization googlevis


    【解决方案1】:

    我不确定您所说的“重叠”是什么意思。数据似乎由一组单调递增的时间戳组成,其中每个时间戳都标有某种类别(水果名称,至少在此示例数据中)。这些类别并不完全连续(尽管它们往往是短暂的),所以当您说“重叠”时,也许这就是您所指的。但这只是数据的性质;没有办法以改变彼此关系的方式“拆分”时间戳。而且您不能选择忽略时间戳的某些数字;这会使数据变得毫无意义。

    为了澄清,时间戳是 19 位数字,表示以 10 为底的数字。这些数字是指自 1970-01-01 UTC 以来经过的纳秒。这是表示时间戳的常用方式(以及自 1970-01-01 UTC 以来的秒数、自 1970-01-01 UTC 以来的毫秒数以及自 1970-01-01 UTC 以来的天数)。

    因此,您可以通过as.double()(也可以使用as.numeric())强制加倍,​​除以1e9,然后使用强制函数as.POSIXct()origin='1970-01-01' 来导出时间戳的POSIXct 表示,它处理自 1970-01-01 UTC 以来的秒数加倍。 (看起来您在代码中执行的操作与此类似,但由于上述问题而无法正常工作。)

    现在,这样做实际上会损失一点精度,因为普遍存在的 double 类型的有效位有 53 个二进制位(52 个显式编码在值的位中,1 个隐式编码(前导 1 位);参见 @ 987654321@),计算出大约 15 个以 10 为基数的数字。这不足以保留传入时间戳中的所有 19 个基数为 10 的数字。但是由于您可能不关心微秒和纳秒,我们可以在这里忽略它。

    我推荐data.table 用于所有表格工作,因为它比基本的 R data.frame 类型更优雅、更强大、更高效。以下是使用 data.table 输入和处理数据的方法:

    ## prepare data
    library(data.table);
    dd <- as.data.table(read.csv('~/Desktop/gazedata.csv.txt',header=T,sep=',',colClasses=c('character','character')));
    dd[,`:=`(dt=as.POSIXct(as.double(rosbagTimestamp)/1e9,origin='1970-01-01'),rosbagTimestamp=NULL)];
    dd2 <- dd[,.(start=min(dt),end=max(dt)),data][order(data)];
    dd2;
    ##           data               start                 end
    ##  1:          0 2015-08-05 18:07:14 2015-08-05 18:10:49
    ##  2:      apple 2015-08-05 18:08:13 2015-08-05 18:10:48
    ##  3:    avocado 2015-08-05 18:07:13 2015-08-05 18:10:01
    ##  4:     banana 2015-08-05 18:07:16 2015-08-05 18:10:48
    ##  5:  blueberry 2015-08-05 18:07:14 2015-08-05 18:10:42
    ##  6:       kiwi 2015-08-05 18:07:27 2015-08-05 18:10:41
    ##  7:      mango 2015-08-05 18:07:17 2015-08-05 18:10:40
    ##  8:     orange 2015-08-05 18:07:27 2015-08-05 18:10:30
    ##  9:     papaya 2015-08-05 18:07:12 2015-08-05 18:09:16
    ## 10:      peach 2015-08-05 18:08:15 2015-08-05 18:10:45
    ## 11:       pear 2015-08-05 18:07:20 2015-08-05 18:07:48
    ## 12: strawberry 2015-08-05 18:07:14 2015-08-05 18:10:20
    ## 13: watermelon 2015-08-05 18:07:30 2015-08-05 18:09:29
    

    现在,关于绘图,您可能不想走这条路,但由于您使用的数据是原始数据(即 POSIXct 时间戳和字符串),您可以使用基本 R 图形函数自己绘制它。我通常更喜欢这个而不是使用像gvisTimeline() 这样的预打包绘图功能,因为它可以更好地控制绘图元素。但它也需要对基本图形框架有广泛的了解,并且在编写绘图代码时通常需要更多的努力和谨慎。

    这是一个演示如何生成与您的屏幕截图相似的绘图:

    ## helper functions
    trunc <- function(x,...) UseMethod('trunc');
    trunc.default <- function(x,...) base::trunc(x,...);
    trunc.POSIXt <- function(x,unit='sec',num=1) { u <- sub(perl=T,'(?<=.)s$','',unit); base::trunc.POSIXt(x,u) - as.integer(format(x,c(sec='%S',second='%S',min='%M',minute='%M',hour='%H',day='%d')[u]))%%num*unname(c(sec=1,second=1,min=60,minute=60,hour=3600,day=86400)[u]); };
    
    ceiling <- function(x,...) UseMethod('ceiling');
    ceiling.default <- function(x,...) base::ceiling(x);
    ceiling.POSIXt <- function(x,unit='sec',num=1) { u <- sub(perl=T,'(?<=.)s$','',unit); trunc.POSIXt(x-.Machine$double.base^(as.integer(log2(as.double(x)))-.Machine$double.digits+1L),unit,num) + num*unname(c(sec=1,second=1,min=60,minute=60,hour=3600,day=86400)[u]); };
    
    ## define plot parameters
    xtick.first <- trunc(min(dd2$start),'hour');
    xtick.last <- ceiling(max(dd2$end),'hour');
    xtick <- seq(xtick.first,xtick.last,'10 min');
    xtick.range <- as.double(difftime(xtick.last,xtick.first,unit='secs'));
    xmin <- xtick.first - xtick.range*20/100;
    xmax <- xtick.last + xtick.range*5/100;
    xlim <- c(xmin,xmax);
    ydiv <- 0:nrow(dd2);
    ytick <- nrow(dd2):1-0.5;
    ymin <- ydiv[1];
    ymax <- ydiv[length(ydiv)];
    ylim <- c(ymin,ymax);
    line.grey <- 'grey';
    bg.grey <- '#dddddd';
    bg.white <- 'white';
    
    ## plot
    par(xaxs='i',yaxs='i',mar=c(5,1,1,1));
    plot(NA,xlim=xlim,ylim=ylim,axes=F,ann=F);
    rect(xmin,(ymax-1):ymin,xmax,ymax:(ymin+1),col=c(bg.white,bg.grey),border=NA);
    with(expand.grid(y=ytick,x=xtick),segments(x,y+0.5,x,y-0.5,col=rep(c(line.grey,bg.white),len=length(ytick))));
    abline(h=ydiv,lwd=2,col=line.grey);
    abline(v=xlim,lwd=2,col=line.grey);
    barheight <- 0.75;
    with(dd2,rect(start,ytick-barheight/2,end,ytick+barheight/2,col=rainbow(nrow(dd2)),border=NA));
    xtick.ishour <- c(T,format(xtick[-1],'%M')=='00');
    text(xtick,0,pos=1,ifelse(xtick.ishour,format(xtick,'%H:%M'),format(xtick,':%M')),font=ifelse(xtick.ishour,2,1),xpd=NA);
    text(xtick.first,ytick,pos=2,dd2[,data]);
    text(dd2[,end],ytick,pos=4,dd2[,data]);
    

    【讨论】:

    • 您创建的图表仍有时间重叠。我的意思是西瓜和草莓的一部分在现实中发生在同一时间间隔内(在我们的实验中不是这样)。你有这方面的秘诀吗?
    • 我只是根据数据。每个类别的时间戳相互交织。如果您的实验没有涉及此类重叠的时间戳,那么数据一定是不正确的。
    猜你喜欢
    • 2021-04-13
    • 2019-11-01
    • 1970-01-01
    • 2017-01-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多