Reputation: 45
I have a dataframe with values like following
df=data.frame(c(0,0,NA),c(0,0,NA),c(0,1,0),c(1,0,0),c(0,0,1),c(1,0,1),c(0,1,0),c(1,0,0),c(1,0,0),c(0,0,1),c(0,0,1))
0 0 0 1 0 1 0 1 1 0 0
0 0 1 0 0 0 1 0 0 0 0
NA NA 0 0 1 1 0 0 0 1 1
I have to count the number of consecutive 0's. The first 0 has to be tranformed to .95
.
If there are 2 consecutive 0's then the second one has to be converted to .6
.
If there are 3 or more consecutive 0's they have to be transformed to .4
.
If the value is 1 it should be left alone.
In the example shown the dataframe will be transformed to this:
0.95 0.6 0.4 1 0.95 1 0.95 1 1 0.95 0.6
0.95 0.6 1 0.95 0.6 0.4 1 0.95 0.6 0.4 0.4
NA NA 0.95 0.6 1 1 0.95 0.6 0.4 1 1
This has to be done using the base package only.
Upvotes: 1
Views: 108
Reputation: 25225
Another option:
df = data.frame(c(0,0),c(0,0),c(0,1),c(1,0),c(0,0),c(1,0),c(0,1),c(1,0),c(1,0),c(0,0),c(0,0))
y <- c(0.95, 0.6, rep(0.4, ncol(df) - 2))
t(apply(df, 1L, function(x) {
with(rle(x), {
unlist(mapply(function(v, l) if(!is.na(v) && v==0L) y[seq.int(l)] else rep(v, l), values, lengths))
})
}))
output:
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11]
[1,] 0.95 0.6 0.40 1.00 0.95 1.0 0.95 1.00 1.0 0.95 0.6
[2,] 0.95 0.6 1.00 0.95 0.60 0.4 1.00 0.95 0.6 0.40 0.4
[3,] NA NA 0.95 0.60 1.00 1.0 0.95 0.60 0.4 1.00 1.0
Upvotes: 2
Reputation: 14764
You could try:
conditions <- data.frame(cond = c(0, 1, 2, 3), vals = c(1, .95, .6, .4))
transp <- as.data.frame(t(df))
transp[] <- lapply(transp,
function(x)
ave(x,
!is.na(x),
FUN =
function(i) conditions[, 2][
match(ave(i, cumsum(i != 0), FUN = function(y) pmin(cumsum(y == 0), 3)), conditions[, 1])
]))
t(transp)
Output:
c.0..0..NA. c.0..0..NA..1 c.0..1..0. c.1..0..0. c.0..0..1. c.1..0..1. c.0..1..0..1 c.1..0..0..1 c.1..0..0..2 c.0..0..1..1 c.0..0..1..2
V1 0.95 0.6 0.40 1.00 0.95 1.0 0.95 1.00 1.0 0.95 0.6
V2 0.95 0.6 1.00 0.95 0.60 0.4 1.00 0.95 0.6 0.40 0.4
V3 NA NA 0.95 0.60 1.00 1.0 0.95 0.60 0.4 1.00 1.0
Upvotes: 2
Reputation: 16978
A very ugly solution could be:
dt <- data.frame(c(0,0),c(0,0),c(0,1),c(1,0),c(0,0),c(1,0),c(0,1),c(1,0),c(1,0),c(0,0),c(0,0))
for (i in 1:dim(dt)[1]) {
count <- 0
for (j in 1:dim(dt)[2]) {
if (dt[i,j] == 0) {
if (count == 0) dt[i,j] <- 0.95
if (count == 1) dt[i,j] <- 0.6
if (count >= 2) dt[i,j] <- 0.4
count <- count + 1
} else { count <- 0 }
}
}
Upvotes: 2