Reputation: 889
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.
# 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
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
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
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