Propagating Data Within a Vector

propagating data within a vector

Package zoo has a function na.locf():

R> library("zoo")
R> na.locf(c(1, 2, 3, 4))
[1] 1 2 3 4
R> na.locf(c(1, NA, NA, 2, 3, NA, 4))
[1] 1 1 1 2 3 3 4

na.locf: Last Observation Carried Forward;
Generic function for replacing each ‘NA’ with the most recent non-‘NA’ prior to it.

See the source code of the function na.locf.default, it doesn't need a for-loop.

How can I propagate const when returning a std::vector int* from a const method?

You're asking for std::experimental::propagate_const. But since it is an experimental feature, there is no guarantee that any specific toolchain is shipped with an implementation. You may consider implementing your own. There is an MIT licensed implementation, however. After including the header:

using namespace xpr=std::experimental;
///...
std::vector<xpr::propagate_const<int*>> my_ptr_vec;

Note however that raw pointer is considered evil so you may need to use std::unique_ptr or std::shared_ptr. propagate_const is supposed to accept smart pointers as well as raw pointer types.

How to propagate value of a cell to other rows based on criteria in R

 transform(A,correct=zoo::na.locf0(correct,T))
index A B correct
1 1 1 1 0
2 2 1 2 0
3 3 1 3 0
4 4 2 1 1
5 5 2 2 1
6 6 2 3 1

How to na.locf in R without using additional packages

Extracted from zoo::na.locf.default

fillInTheBlanks <- function(S) {
L <- !is.na(S)
c(S[L][1], S[L])[cumsum(L)+1]
}

See also here.

Custom Attribute Propagation in R

Even simple addition can destroy attributes. In this next example, only y's attributes remain:

x <- 1:5
attr(x, "foo") <- letters[1:3]

y <- 6:10
attr(x, "foo") <- letters[4:6]

x + y
## [1] 7 9 11 13 15
## attr(,"foo")
## [1] "d" "e" "f"

As DWin said, they are fragile; probably too fragile for what you want.


To expand on flodel's point, a common approach that will robustly propagate everything is to use a list with a class attribute.

Models returned by lm are a typical example of this. The output is too big to show here, but if you do unclass on an lm object, you'll see that it is just a list.

model <- lm(Sepal.Length ~ Sepal.Width + Species, iris)
unclass(model)

Then you can overload any functions (which are now S3 methods) to deal with your new class.

Propagating value based on another value calculated in the previous group

Here is one option with for loop

v <- 0.001000000
lst <- vector("list", nrow(df))
for(i in rev(seq_along(lst))) {
e1 <- v * exp(df$k[i] *(df$end_depth[i] -
seq(df$start_depth[i], df$end_depth[i], by = 1)))
lst[[i]] <- e1
v <- e1[1]

}

-output

lst
#[[1]]
#[1] 0.02922428 0.02550820 0.02226465 0.01943353 0.01696241 0.01480552

#[[2]]
#[1] 0.014805519 0.012935817 0.011302229 0.009874938 0.008627890 0.007538325

#[[3]]
#[1] 0.007538325 0.006599540 0.005777667 0.005058146 0.004428230 0.003876761

#[[4]]
#[1] 0.003876761 0.003373666 0.002935859 0.002554867 0.002223316 0.001934792

#[[5]]
#[1] 0.001934792 0.001695538 0.001485869 0.001302128 0.001141108 0.001000000

If we are using tidyverse, then pmap and accumulate_right can be used

library(purrr)
pmap(df, ~ exp(..3 *(..2 - seq(..1, ..2, by = 1)))) %>%
accumulate_right(~ .x[1] * .y, .init = 0.001000000) %>%
head(., -1)
#[[1]]
#[1] 0.02922428 0.02550820 0.02226465 0.01943353 0.01696241 0.01480552

#[[2]]
#[1] 0.014805519 0.012935817 0.011302229 0.009874938 0.008627890 0.007538325

#[[3]]
#[1] 0.007538325 0.006599540 0.005777667 0.005058146 0.004428230 0.003876761

#[[4]]
#[1] 0.003876761 0.003373666 0.002935859 0.002554867 0.002223316 0.001934792

#[[5]]
#[1] 0.001934792 0.001695538 0.001485869 0.001302128 0.001141108 0.001000000

Propagating calculation along rows

Here is a fairly straightforward method in base R.

with(df, cumsum(x + ifelse(is.na(ed0), 0, ed0) + c(0, head(kd, -1))))
[1] 0.2432977 30.2080240 70.1648789

To break this down, x remains as it is and c(0, head(kd, -1)) setups a lagged vector of kd where the initial value is 0. ifelse(is.na(ed0), 0, ed0) checks if each element of ed0 is NA and replaces it with 0 if TRUE. These three terms are summed together and the resulting vector is given to cumsum to produce a cumulative sum. Finally, with is used to reduce typing.

Propagating values from the leaf to the root

Inside your for save the minVal from all children and return minVal instead of currVal.

for(auto& neighbor: rootNode->children) {
minVal = min(minVal, dfs(neighbor, minVal, currVal));
}
return minVal;

That way you're always returning the minVal, through the recursion all the way to the first call.

Edit: Explanation

I'll use the tree you provided in your question as an example. We'll start by entering the tree at the root(0). It'll add 0 to the currVal, won't enter the first if, then enter the for. Once it's there, the function will be called again, from the first child.

At the first node (5), it'll add that value, check if it's the end, and go to the next node (4), adds again, currVal is now 9. Then, since (4) has no children, it'll return min(currVal, minVal). At this point, minVal is INT_MAX, so it returns 9.

Once this value is returned, we go back to the function that called it, which was at node(5), exactly at the point when we called (4), and we'll (with my modification) compare whichever value it returned with minVal.

min(minVal, dfs(neighbor, minVal, currVal))

At this point, it's important to notice that the current minVal is still INT_MAX, as it's not a reference, and this was the value passed to the function. And as a result, we now set it to 9.

If (5) had other children, we would now enter a new instance of dfs and at the once we had a result, compare that value with 9, but since we don't, we end the for loop and return minVal, going back to the root node(0).

From there, I believe you can guess what happens, we enter node(3) which branches to (2)->(1)->(1) and (0)->(10), returning 7 and 13 to the for loop respectively, and node (6) will finally also return 7 to (0)'s for loop.

In the end, (0) will first compare INT_MAX with 9, then with 7 and finally with 7 again, returning 7 to getCheapestCost.

In short:

Your code will keep entering dfs until it finds a node without children, once that happens, it'll return the minVal it got from that node, and return to the function that called it, which is the parent node.

Once in the parent node, you need to check which children provided the minimum minVal, by comparing that with your previous minVal (from other children, branches or INT_MAX). After checking all children, minValue is returned to the next parent, which compares with its children until it reaches the root node.

Convert factor to POSIXlt with propagating date in R

library(zoo)  # For the na.locf function

df = data.frame(date=t)

# Put date and time in separate columns
df$time = gsub(".*; (.*)","\\1", df$date)
df$date = as.Date(df$date, format="%d.%m.%Y")

# Fill missing df$date values
df$date = na.locf(df$date)

# Convert to POSIXct
df$date = as.POSIXct(paste(df$date, df$time))
df = df[,1, drop=FALSE]

df

date
1 2013-01-20 00:05:00
2 2013-01-20 00:15:00
3 2013-01-20 00:25:00
4 2013-01-20 00:35:00
5 2013-01-20 00:45:00
6 2013-01-20 02:05:00
7 2013-01-25 20:38:00
8 2013-01-25 20:48:00
9 2013-01-25 20:58:00
10 2013-01-25 21:08:00


Related Topics



Leave a reply



Submit