SimpleNEasy
SimpleNEasy

Reputation: 889

Loop, extract and calculate a series

I have a data-frame which consists of 12 columns and n rows. I want to check the values from column 3:10 for each row. If the value is 1, I want to calculate a series. Consider the following data-frame:

  A     B   b7  b6  b5   b4  b3  b2  b1  b0 
  0    190   1   0   0   0   0   0   0   0
  1    700   1   0   0   0   0   0   0   1
  2    540   1   0   0   0   0   0   1   1

I want to loop through each row and check the value from b7:b0. if the value is 1, then calculate the sum based on : sum= (1* x^ (-position) ). based on the above example , sum should be:

1.First row : sum= 1 * x ^ (-7)

2.Second row : sum= 1 * x ^ (-7) + 1 * x ^ (-0)

3.Third row : sum= 1 * x ^ (-7) + 1 * x ^ (-1) + 1 * x ^ (-0)

where X is a constant value. The result should be added to the original data-frame :

  A     B   b7  b6  b5   b4  b3  b2  b1  b0 Result
  0    190   1   0   0   0   0   0   0   0   number
  1    700   1   0   0   0   0   0   0   1    ..
  2    540   1   0   0   0   0   0   1   1    ..

For the splitting and extracting the data, I have followed two approaches( as best to my knowledge) whether to use subset or follow the classic way of splitting.

Classic Approach

# loop through the data-frame ( here number of records n=3)
# df is the data-frame
for (i in 1:3){
 y<- df[i,3:10] 
}

# the above code extracts one row for each iteration with columns from b7:b0. gives an output :
b7  b6   b5   b4  b3  b2  b1  b0
1    0   0    0   0   0   1   1

Subset Approach

# Subset the df into new data-frame which only contains the b7:b0
  newDF<-subset.data.frame(df,select=b7:b0 )

My question, how to loop through the data-frame, check the values, and calculate the series. I'm only thinking to use many IF statements to check each value. I'm sure there are other alternatives approaches.

Any suggestions ?

Upvotes: 0

Views: 325

Answers (3)

Aur&#232;le
Aur&#232;le

Reputation: 12819

You can hide the loop in a apply() function:

df <- read.table(text =
"  A     B   b7  b6  b5   b4  b3  b2  b1  b0 
  0    190   1   0   0   0   0   0   0   0
1    700   1   0   0   0   0   0   0   1
2    540   1   0   0   0   0   0   1   1",
header = TRUE)

X <- 3
df$Result <- apply(df[, 3:10], 1, function(row) sum(row * X ^ (-7:-0)))
df
#   A   B b7 b6 b5 b4 b3 b2 b1 b0       Result
# 1 0 190  1  0  0  0  0  0  0  0 0.0004572474
# 2 1 700  1  0  0  0  0  0  0  1 1.0004572474
# 3 2 540  1  0  0  0  0  0  1  1 1.3337905807

Edit: better solution from @jogo in the comments:

as.matrix(df[, 3:10]) %*% (1/X)^(7:0)
##              [,1]
## [1,] 0.0004572474
## [2,] 1.0004572474
## [3,] 1.3337905807

Upvotes: 2

jogo
jogo

Reputation: 12559

Here is a solution with poly() and matrix multiplication:

str <- "A,B,b7,b6,b5,b4,b3,b2,b1,b0 
0,190,1,0,0,0,0,0,0,0
2,540,1,0,0,0,0,0,1,1
1,700,1,0,0,0,0,0,0,1"

file <- textConnection(str)

df <- read.table(file, header = T, sep = ",")
x <- 2
as.matrix(df[,3:10]) %*% rev(c(1, poly(x=1/x, degree=7, raw = TRUE)))
# > as.matrix(df[,3:10]) %*% rev(c(1, poly(x=1/x, degree=7, raw = TRUE)))
#           [,1]
# [1,] 0.0078125
# [2,] 1.5078125
# [3,] 1.0078125

I used the data definition from the answer of @Wietze314
variants:

as.matrix(df[,9:3]) %*% t(poly(x=1/x, degree=7, raw = TRUE)) + df$b0
tcrossprod(as.matrix(df[,9:3]), poly(x=1/x, degree=7, raw = TRUE)) + df$b0

Upvotes: 3

Wietze314
Wietze314

Reputation: 6020

I think you can do this with a vector calculation and apply as follows

the data:

str <- "A,B,b7,b6,b5,b4,b3,b2,b1,b0 
0,190,1,0,0,0,0,0,0,0
2,540,1,0,0,0,0,0,1,1
1,700,1,0,0,0,0,0,0,1"

file <- textConnection(str)

dat <- read.table(file, header = T, sep = ",")
x = 2

The method:

colSums(apply(dat[,3:10], 1, function(i) i*x^(-7:0)))

The result:

[1] 0.0078125 1.5078125 1.0078125

Upvotes: 2

Related Questions