我有一个包含日期和价格的数据框。对于某些日期,价格为NA
。我试图在" last"之间的日期中找到最大的间隔。 (以连续顺序)NA
价格和最后非NA价格。我完全迷失了 - 我怀疑difftime
需要被使用,但我无法想出这个条件。
E.g:
DF = structure(list(rollup_date = c("2017-05-01 00:00:00", "2017-05-02 00:00:00",
"2017-05-03 00:00:00", "2017-05-04 00:00:00", "2017-05-05 00:00:00",
"2017-05-06 00:00:00", "2017-05-07 00:00:00", "2017-05-08 00:00:00",
"2017-05-09 00:00:00", "2017-05-10 00:00:00", "2017-05-11 00:00:00",
"2017-05-12 00:00:00", "2017-05-13 00:00:00", "2017-05-14 00:00:00",
"2017-05-15 00:00:00"), RegularPrice = c(6.47, 6.47, 6.47, 6.47,
NA, NA, NA, NA, NA, NA, NA, 6.47, NA, 6.47, 6.47)), .Names = c("rollup_date",
"RegularPrice"), row.names = 145624:145638, class = "data.frame")
所以,这里的产出是7天(5/11 - 5/04)和1天(5月13日 - 5月5日)。可以存储所有解决方案,然后我选择最大的解决方案。
答案 0 :(得分:1)
DF$rollup_date = as.POSIXct(DF$rollup_date)
with(rle(is.na(DF$RegularPrice)),
sapply(which(values == TRUE),
function(i) difftime(time1 = DF$rollup_date[cumsum(lengths)[i]],
time2 = DF$rollup_date[cumsum(lengths)[i-1]],
units = "days")))
#[1] 7 1
答案 1 :(得分:1)
为了完整起见,这里还有一个library(data.table)
setDT(DF)[, rollup_date := as.Date(rollup_date)][
, .(last(RegularPrice), last(rollup_date)), by = rleid(is.na(RegularPrice))][
, diff.days := V2 - shift(V2)][
is.na(V1)]
解决方案:
rleid V1 V2 diff.days
1: 2 NA 2017-05-11 7 days
2: 4 NA 2017-05-13 1 days
data.table
强制转换为rollup_date
后,Date
会从字符转换为类POSIXct
(此处不需要NA
)。然后,使用non-NA
函数按rleid()
和NA
值的连续条纹对数据进行分组,选择每个组中的最后一个值。中间结果聚合为5行。
最后,计算每个组之间的日期差异,并仅返回rollup_date
行。
数据需要按sum()
排序,这显然是OP提供的样本数据的情况,但没有明确提及。
聚合仅包括挑选每组中最后一行的值。不涉及mean()
或DF
等其他计算。这类似于过滤.I
。
这也可以通过返回相关的行ID DF
并使用此选项从DF[, last(.I), by = rleid(is.na(RegularPrice))][, V1]
中选择相应的行来实现:
[1] 4 11 12 13 15
setDT(DF)[, rollup_date := as.Date(rollup_date)][ DF[, last(.I), by = rleid(is.na(RegularPrice))][, V1]][ , diff.days := rollup_date - shift(rollup_date)][ is.na(RegularPrice)]
因此,完整的解决方案变为
rollup_date RegularPrice diff.days
1: 2017-05-11 NA 7 days
2: 2017-05-13 NA 1 days
(function($){ $.fn.j360 = function(options) { var defaults = { clicked: false, currImg: 1 } var options = jQuery.extend(defaults, options); return this.each(function() { var $obj = jQuery(this); var aImages = {}; $obj.css({ 'margin-left' : 'auto', 'margin-right' : 'auto', 'text-align' : 'center', 'overflow' : 'hide' }); $overlay = $obj.clone(true); $overlay.html('<img src="images/loader.gif" class="loader" style="margin-top:' + ($obj.height()/2 - 15) + 'px" />'); $overlay.attr('id', 'view_overlay'); $overlay.css({ 'position' : 'absolute', 'z-index': '5', 'top' : $obj.offset().top, 'left' : $obj.offset().left, 'background' : '#fff' }); $obj.after($overlay); $obj.after('<div id="colors_ctrls"></div>'); jQuery('#colors_ctrls').css({ 'width' : $obj.width(), 'position' : 'absolute', 'z-index': '5', 'top' : $obj.offset().top + $obj.height - 50, 'left' : $obj.offset().left }); var imageTotal = 0; jQuery('img', $obj).each(function() { aImages[++imageTotal] = jQuery(this).attr('src'); preload(jQuery(this).attr('src')); }) var imageCount = 0; jQuery('.preload_img').load(function() { if (++imageCount == imageTotal) { $overlay.animate({ 'filter' : 'alpha(Opacity=0)', 'opacity' : 0 }, 100); $obj.html('<img src="' + aImages[1] + '" />'); $overlay.bind('mousedown touchstart', function(e) { if (e.type == "touchstart") { options.currPos = window.event.touches[0].pageX; } else { options.currPos = e.pageX; } options.clicked = true; return false; }); jQuery(document).bind('mouseup touchend', function() { options.clicked = false; }); jQuery(document).bind('mousemove touchmove', function(e) { if (options.clicked) { var pageX; if (e.type == "touchmove") { pageX = window.event.targetTouches[0].pageX; } else { pageX = e.pageX; } var width_step = 50; if (Math.abs(options.currPos - pageX) >= width_step) { if (options.currPos - pageX >= width_step) { options.currImg++; if (options.currImg > imageTotal) { options.currImg = 1; } } else { options.currImg--; if (options.currImg < 1) { options.currImg = imageTotal; } } options.currPos = pageX; $obj.html('<img src="' + aImages[options.currImg] + '" />'); } } }); } }); if (jQuery.browser.msie || jQuery.browser.mozilla || jQuery.browser.opera || jQuery.browser.safari ) { jQuery(window).resize(function() { onresizeFunc($obj, $overlay); }); } else { var supportsOrientationChange = "onorientationchange" in window, orientationEvent = supportsOrientationChange ? "orientationchange" : "resize"; window.addEventListener(orientationEvent, function() { onresizeFunc($obj, $overlay); }, false); } onresizeFunc($obj, $overlay) }); } }) (jQuery) function onresizeFunc($obj, $overlay){ $obj.css({ 'margin-top' : $(document).height()/2 }); $overlay.css({ 'margin-top' : 200, 'top' : $obj.offset().top, 'left' : $obj.offset().left }); jQuery('#colors_ctrls').css({ 'top' : $obj.offset().top + $obj.height - 50, 'left' : $obj.offset().left }) } function preload(image) { if (typeof document.body == "undefined") return; try { var div = document.createElement("div"); var s = div.style; s.position = "absolute"; s.top = s.left = 0; s.visibility = "hidden"; document.body.appendChild(div); div.innerHTML = "<img class=\"preload_img\" src=\"" + image + "\" />"; } catch(e) { // Error. Do nothing. } };