Element wise mean from data frame [closed] - r

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
I have a data frame with 3 columns and 16 rows. Each element has values like row1 values are (0.9, 0.9, 1.0), (0.7,0.9, 1.0), (0.9, 0.9, 1.0). I want element wise mean e.g., (0.9+0.7+0.9/3), (0.9+0.9+0.9/3), (1.0+1.0+1.0/3) and store the result as new column. Any suggestions?
SHO1 SHO2 SHO3
1 0.7, 0.9, 1.0 0.9, 0.9, 1.0 0.7, 0.9, 1.0
2 0.7, 0.9, 1.0 0.9, 0.9, 1.0 0.7, 0.9, 1.0
3 0.0, 0.0, 0.1 0.9, 0.9, 1.0 0.0, 0.0, 0.1
expected out for row1:
0.7+0.9+0.7/3, 0.9+0.9+0.9/3, 1.0+1.0+1.0/3

Based on the dput output by the OP (in the comments), we found that the columns in 'df1' are not 'strings'. Infact each element of each column is a list. So, instead of doing strsplit (as I suggested earlier), we loop through the columns with lapply and rbind the list elements (do.call(rbind). The output 'list' contains 'matrix' as list elements.
We can use Reduce to take the elementwise sum (Reduce('+', ..), and divide by the length of the list i.e. 3.
The matrix output ('m1') can be pasted together rowwise (do.call(paste) after converting to 'data.frame' and create a new column in the original dataset ('df1').
m1 <- Reduce('+', lapply(df1, function(x) do.call(rbind, x)))/ncol(df1)
df1$newCol <- do.call(paste, c(as.data.frame(m1), sep=", "))
df1
# SHO1 SHO2 SHO3
#1 0.9, 0.9, 1.0 0.7, 0.9, 1.0 0.9, 0.9, 1.0
#2 0.9, 0.9, 1.0 0.7, 0.9, 1.0 0.9, 0.9, 1.0
#3 0.3, 0.5, 0.7 0.7, 0.9, 1.0 0.3, 0.5, 0.7
#4 0.7, 0.9, 1.0 0.9, 0.9, 1.0 0.9, 0.9, 1.0
# newCol
#1 0.833333333333333, 0.9, 1
#2 0.833333333333333, 0.9, 1
#3 0.433333333333333, 0.633333333333333, 0.8
#4 0.833333333333333, 0.9, 1
data
df1 <- structure(list(SHO1 = structure(list(VH = c(0.9, 0.9, 1),
VH = c(0.9,
0.9, 1), M = c(0.3, 0.5, 0.7), H = c(0.7, 0.9, 1)), .Names = c("VH",
"VH", "M", "H")), SHO2 = structure(list(H = c(0.7, 0.9, 1), H = c(0.7,
0.9, 1), H = c(0.7, 0.9, 1), VH = c(0.9, 0.9, 1)), .Names = c("H",
"H", "H", "VH")), SHO3 = structure(list(VH = c(0.9, 0.9, 1),
VH = c(0.9, 0.9, 1), M = c(0.3, 0.5, 0.7), VH = c(0.9, 0.9,
1)), .Names = c("VH", "VH", "M", "VH"))), .Names = c("SHO1",
"SHO2", "SHO3"), row.names = c(NA, 4L), class = "data.frame")

Related

Better illustration of very small differences in graphs

I'm having to generate a graph using different internet links. As the data input has very close values, the graph has practically no differences.
Is there a way to make this difference more apparent?
Here is the code used:
generateGraphic <- function(gFile, wifiFile, wifigFile){
gData <- read.csv(file=gFile, header=FALSE)
wifiData <- read.csv(file=wifiFile, header=FALSE)
wifigData <- read.csv(file=wifigFile, header=FALSE)
x = gData[,1]
y1 = gData[,2]
print(y1)
y2 = wifiData[,2]
print(y2)
y3 = wifigData[,2]
print(y3)
plot(x, y1, type="b", pch = 16, xlab="Tempo (s)", ylab="Probabilidade", xaxt="n", yaxt="n")
axis(1, at = seq(0, 4, by = 0.4), las=2)
axis(2, at = seq(0, 1, by = 0.1), las=2)
lines(x, y2, type="b", col="dark gray", pch = 15)
lines(x, y3, type="b", col="light gray", pch = 8)
legend("topleft",
legend = c("4G", "WiFi", "WiFi4G"),
col = c("black", "dark gray", "light gray"),
pch = c(16, 15, 8))
}
Here is a example of the input data:
Wifi Link
0 0.0
0.1 0.20326429999999998
0.2 0.4248706
0.3 0.5867006
0.4 0.7030588999999999
0.5 0.7866605
0.6 0.8467247999999999
0.7 0.8898784999999999
0.8 0.9208824999999999
0.9 0.9431575999999999
1 0.9591613
1.1 0.9706591999999999
1.2 0.9789199999999999
1.3 0.9848549999999999
1.4 0.9891190999999999
1.5 0.9921825999999999
1.6 0.9943835999999999
1.7 0.9959648999999999
1.8 0.9971009999999999
1.9 0.9979172
2 0.9985035999999999
4G Link
0 0.0
0.1 0.2032832
0.2 0.4249017
0.3 0.5867356
0.4 0.703093
0.5 0.7866915
0.6 0.8467515999999999
0.7 0.8899009999999999
0.8 0.9209010999999999
0.9 0.9431725999999999
1 0.9591732
1.1 0.9706686
1.2 0.9789274
1.3 0.9848606999999999
1.4 0.9891234999999999
1.5 0.9921859
1.6 0.9943862
1.7 0.9959669
1.8 0.9971025
1.9 0.9979184
2 0.9985044999999999
2.1 0.9989256
2.2 0.9992281
2.3 0.9994455
2.4 0.9996016
You could plot the differences to 4G as reference.
I would put the value columns into a list, and adapt their lengths by filling with NA.
values <- list(gData=gData$V2, wifiData=wifiData$V2, wifigData=wifigData$V2)
After that you may cbind to a matrix m.
m <- do.call(cbind, lapply(values, `length<-`, max(lengths(values))))
Since 4G is in first column, subtract iot from the other columns
m <- m[, 2:3] - m[, 1]
and use matplot.
matplot(m, type='b', xaxt='n', pch=c(15, 8), col=1, xlab='Tempo (s)',
ylab='Probabilidade', main='Diferencias')
sq <- seq.int(0, by=.1, length.out=nrow(m))
axis(1, sq[seq_along(sq) %% 4 == 1], at=seq_along(sq)[seq_along(sq) %% 4 == 1])
abline(h=0, col=8)
mtext('4G', 4, -2, at=-.5e-5, las=2, col=8, font=2)
legend("bottomright", leg=c("WiFi", "WiFi4G"), horiz=T, pch=c(15, 8), bty='n')
You could also turn it around of course.
m <- do.call(cbind, lapply(values, `length<-`, max(lengths(values))))
m <- m[, 1] - m[, 2:3]
matplot(m, type='b', xaxt='n', pch=c(15, 8), col=1, xlab='Tempo (s)',
ylab='Probabilidade', main='Diferencias')
sq <- seq.int(0, by=.1, length.out=nrow(m))
axis(1, sq[seq_along(sq) %% 4 == 1], at=seq_along(sq)[seq_along(sq) %% 4 == 1])
legend("bottomright", leg=c("4G vs. WiFi", "4G vs. WiFi4G"), horiz=T, pch=c(15, 8),
bty='n')
Data:
gData <- structure(list(V1 = c(0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8,
0.9, 1, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2, 2.1,
2.2, 2.3, 2.4), V2 = c(0, 0.203385231442384, 0.425002665444611,
0.586833487363752, 0.703191551616986, 0.7867914923001, 0.846852450869833,
0.889999103106634, 0.921001598894712, 0.943272154043885, 0.959273034150037,
0.970768887392538, 0.979028541813682, 0.984959224443878, 0.989223699201295,
0.992284899754003, 0.994485588797307, 0.996068229156018, 0.997202959924694,
0.998019756784877, 0.998605023394967, 0.999025567967921, 0.999327477772277,
0.999546146749613, 0.999701921229212)), row.names = c(NA, -25L
), class = "data.frame")
wifiData <- structure(list(V1 = c(0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8,
0.9, 1, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2), V2 = c(0,
0.2032643, 0.4248706, 0.5867006, 0.7030589, 0.7866605, 0.8467248,
0.8898785, 0.9208825, 0.9431576, 0.9591613, 0.9706592, 0.97892,
0.984855, 0.9891191, 0.9921826, 0.9943836, 0.9959649, 0.997101,
0.9979172, 0.9985036)), class = "data.frame", row.names = c(NA,
-21L))
wifigData <- structure(list(V1 = c(0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8,
0.9, 1, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2, 2.1,
2.2, 2.3, 2.4), V2 = c(0, 0.2032832, 0.4249017, 0.5867356, 0.703093,
0.7866915, 0.8467516, 0.889901, 0.9209011, 0.9431726, 0.9591732,
0.9706686, 0.9789274, 0.9848607, 0.9891235, 0.9921859, 0.9943862,
0.9959669, 0.9971025, 0.9979184, 0.9985045, 0.9989256, 0.9992281,
0.9994455, 0.9996016)), class = "data.frame", row.names = c(NA,
-25L))
Since you are dealing with probabilities, you can convert them to odds very easily:
odds_wifi <- wifiData[[2]] / (1-wifiData[[2]])
odds_gData <- gData[[2]] / (1-gData[[2]])
And depending on your set-up, it might make sense to compare them with an odds ratio:
OR <- odds_wifi / odds_gData
plot(x, OR, type="b", pch = 16, xlab="Tempo (s)",
ylab="RelaciĆ³n de probabilidades")

bnlearn Error: Wrong number of conditional probability distributions

I am learning to work with bnlearn and I keep running into the following error in the last line of my code below:
Error in custom.fit(dag, cpt) : wrong number of conditional probability distributions
What am I doing wrong?
modelstring(dag)= "[s][r][nblw|r][nblg|nblw][mlw|s:r][f|s:r:mlw][mlg|mlw:f]
[mlgr|mlg:nblg]"
###View DAG Specifics
dag
arcs(dag)
nodes(dag)
# Create Levels
State <- c("State0", "State1")
##Create probability distributions given; these are all 2d b/c they have 1 or 2 nodes
cptS <- matrix(c(0.6, 0.4), ncol=2, dimnames=list(NULL, State))
cptR <- matrix(c(0.7, 0.3), ncol=2, dimnames=list(NULL, State))
cptNBLW <- matrix(c(0.95, 0.05, 0.05, 0.95), ncol=2, dimnames=list(NULL, "r"= State))
cptNBLG <- matrix(c(0.9, 0.099999999999999998, 0.2, 0.8), ncol=2, dimnames=list(NULL,
"nblw"=State))
cptMLG <- matrix(c(0.95, 0.05, 0.4, 0.6, 0.2, 0.8, 0.05, 0.95),ncol=2,nrow = 2,
dimnames=list("mlw"= State, "f"=State))
cptMLGR <- matrix(c(0.6,0.4,0.95,0.05,0.2,0.8,0.55,0.45),ncol=2,nrow = 2,
dimnames=list("mlg"= State, "nblg"=State))
cptMLW <-matrix(c(0.95, 0.05, 0.1, 0.9, 0.2, 0.8, 0.01, 0.99), ncol=2,nrow = 2,byrow = TRUE,
dimnames=list("r"= State, "s"=State))
# Build 3-d matrices( becuase you have 3 nodes, you can't use the matrix function; you
have to build it from scratch)
cptF <- c(0.05, 0.95, 0.4, 0.6, 0.9, 0.1, 0.99, 0.01, 0.9, 0.1, 0.95, 0.05, 0.95, 0.05, 0.99,
0.01)
dim(cptF) <- c(2, 2, 2, 2)
dimnames(cptF) <- list("s"=State, "r"=State, "mlw"=State)
###Create CPT Table
cpt <- list(s = cptS, r = cptR, mlw = cptMLW,nblw= cptNBLW,
mlg= cptMLG, nblg= cptNBLG, mlgr= cptMLGR)
# Construct BN network with Conditional Probability Table
S.net <- custom.fit(dag,cpt)
Reference: https://rpubs.com/sarataheri/bnlearnCGM
You have several errors in your CPT definitions. Primarily, you need to make sure that:
the number of probabilities supplied are equal to the product of the number of states in the child and parent nodes,
that the number of dimensions of the matrix/array is equal to the number of parent nodes plus one, for the child node,
the child node should be given in the first dimension when the node dimension is greater than one.
the names given in the dimnames arguments (e.g. the names in dimnames=list(ThisName = ...)) should match the names that were defined in the DAG, in your case with modelstring and in my answer with model2network. (So my earlier suggestion of using dimnames=list(cptNBLW = ...) should be dimnames=list(nblw = ...) to match how node nblw was declared in the model string)
You also did not add node f into your cpt list.
Below is your code with comments where things have been changed. (I have commented out the offending lines and added ones straight after)
library(bnlearn)
dag <- model2network("[s][r][nblw|r][nblg|nblw][mlw|s:r][mlg|mlw:f][mlgr|mlg:nblg][f|s:r:mlw]")
State <- c("State0", "State1")
cptS <- matrix(c(0.6, 0.4), ncol=2, dimnames=list(NULL, State))
cptR <- matrix(c(0.7, 0.3), ncol=2, dimnames=list(NULL, State))
# add child node into first slot of dimnames
cptNBLW <- matrix(c(0.95, 0.05, 0.05, 0.95), ncol=2, dimnames=list(nblw=State, "r"= State))
cptNBLG <- matrix(c(0.9, 0.099999999999999998, 0.2, 0.8), ncol=2, dimnames=list(nblg=State,"nblw"=State))
# Use a 3d array and not matrix, and add child node into dimnames
# cptMLG <- matrix(c(0.95, 0.05, 0.4, 0.6, 0.2, 0.8, 0.05, 0.95),ncol=2,nrow = 2, dimnames=list("mlw"= State, "f"=State))
cptMLG <- array(c(0.95, 0.05, 0.4, 0.6, 0.2, 0.8, 0.05, 0.95),dim=c(2,2,2), dimnames=list(mlg = State, "mlw"= State, "f"=State))
# cptMLGR <- matrix(c(0.6,0.4,0.95,0.05,0.2,0.8,0.55,0.45),ncol=2,nrow = 2, dimnames=list("mlg"= State, "nblg"=State))
cptMLGR <- array(c(0.6,0.4,0.95,0.05,0.2,0.8,0.55,0.45), dim=c(2,2,2), dimnames=list(mlgr=State, "mlg"= State, "nblg"=State))
# cptMLW <-matrix(c(0.95, 0.05, 0.1, 0.9, 0.2, 0.8, 0.01, 0.99), ncol=2,nrow = 2,byrow = TRUE, dimnames=list("r"= State, "s"=State))
cptMLW <-array(c(0.95, 0.05, 0.1, 0.9, 0.2, 0.8, 0.01, 0.99), dim=c(2,2,2), dimnames=list(mlw=State, "r"= State, "s"=State))
# add child into first slot of dimnames
cptF <- c(0.05, 0.95, 0.4, 0.6, 0.9, 0.1, 0.99, 0.01, 0.9, 0.1, 0.95, 0.05, 0.95, 0.05, 0.99, 0.01)
dim(cptF) <- c(2, 2, 2, 2)
dimnames(cptF) <- list("f" = State, "s"=State, "r"=State, "mlw"=State)
# add missing node f into list
cpt <- list(s = cptS, r = cptR, mlw = cptMLW,nblw= cptNBLW, mlg= cptMLG, nblg= cptNBLG, mlgr= cptMLGR, f=cptF)
# Construct BN network with Conditional Probability Table
S.net <- custom.fit(dag, dist=cpt)

Iterate over character vector in dplyR summarise and use it to assign new column names

I have a character vector with the name of my variables:
variables -> c("w", "x", "y", "z")
I need to create a function that calculates the mean of every variable for a specified parameter (as below for alpha). However, it doesn't rename the columns with the iterating variable names and does not reduce the alpha columns down to one on the left.
calc <- function(df,
parameter,
iteration,
variables){
variable <- sym(variables[iteration])
mean <- df %>% group_by(.dots = parameter) %>%
summarise(variable = mean(!!variable),sd_variable = sd(!!variable))
return(mean)
}
means <- map_dfc(1:length(variables), ~calc(df = input,
parameter = "alpha",
iteration = .,
variables = variables))
Ideally the output df (means) would look like this:
alpha | w | sd_w | x | sd_x | y | sd_y | z | sd_z |
Here is what the input df looks like:
structure(list(time = c(0, 0.1, 0.2, 0.3, 0.4, 0.5, 999.5, 999.6,
999.7, 999.8, 999.9, 1000), w = c(10, 10.0057192322758, 10.0198266325956,
10.040096099625, 10.0637654242843, 10.087779652849, 0.889708853982268,
0.890916575744663, 0.892121389863897, 0.89332329218135, 0.894522278550115,
0.895718344834999), x = c(10, 11.0467963604334, 12.1782709261765,
13.3728962503142, 14.6035317074526, 15.8398164069251, 62.6631746231113,
62.6583134156356, 62.6534565303638, 62.648604016965, 62.6437559251575,
62.6389123047088), y = c(10, 9.89605687874935, 9.59253574727296,
9.11222320249057, 8.48917353431654, 7.76447036695841, 0.00833796964522317,
0.00835876233547079, 0.00837957883570158, 0.00840041916631544,
0.00842128334742553, 0.00844217139885453), z = c(10, 9.05439359565339,
8.21533762023494, 7.48379901688836, 6.85562632179817, 6.3231517466183,
-7.50539460838544, -7.48234149534558, -7.45927733670319, -7.43620225192078,
-7.41311636057114, -7.39001978233681), alpha = c(0.1, 0.1, 0.1,
0.1, 0.1, 0.1, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5), beta = c(0.1, 0.1,
0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1), eta = c(0.1,
0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1), zeta = c(0.1,
0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1), lambda = c(0.95,
0.95, 0.95, 0.95, 0.95, 0.95, 0.95, 0.95, 0.95, 0.95, 0.95, 0.95
), phi = c(5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5), kappa = c(1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), ode_outputs..iteration.. = c(NA,
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA)), row.names = c("1",
"1.1", "1.2", "1.3", "1.4", "1.5", "3.9995", "3.9996", "3.9997",
"3.9998", "3.9999", "3.10000"), class = "data.frame")
Ideally the function would use dplyr and/or baseR.
If I understand you correctly, there's no need to iterate over columns. It can all be done directly in dplyr...
library(tidyverse)
df %>%
group_by(alpha) %>%
summarise(
across(
c(w, x, y, z),
list(mean=mean, sd=sd)
),
.groups="drop"
) %>%
rename_with(function(x) str_sub(x,1,1), ends_with("mean"))
# A tibble: 2 x 9
alpha w w_sd x x_sd y y_sd z z_sd
<dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 0.1 10.0 0.0345 12.8 2.20 9.14 0.875 7.99 1.38
2 0.5 0.893 0.00225 62.7 0.00908 0.00839 0.0000390 -7.45 0.0432

Counterintuitive results for dplyr::between() when using vectors

When using dplyr::between(), I assumed that it would compare each element. However it seems like that is not the case, as shown in the below example.
x <- c(0.2, 0.2, 0.2, 0.5, 0.5, 0.5)
y <- c(0.0, 0.0, 0.0, 0.1, 0.052, -0.3)
z <- c(0.43, 0.52, 0.0, 0.76, 0.85, 0.83)
dplyr::between(x=x, left=y, right=z)
# [1] TRUE TRUE TRUE FALSE FALSE FALSE
For example, in the 3rd element, 0.2 is not between 0.0 and 0.0, but TRUE is returned.
In the 4th element, 0.5 is between 0.052 and 0.85, but FALSE is returned.
Any ideas on what causes this behavior?
dplyr::between only accepts single value in left and right, it cannot work with vector of values.
The behaviour that you expect is present in data.table::between :
x <- c(0.2, 0.2, 0.2, 0.5, 0.5, 0.5)
y <- c(0.0, 0.0, 0.0, 0.1, 0.052, -0.3)
z <- c(0.43, 0.52, 0.0, 0.76, 0.85, 0.83)
data.table::between(x=x, lower=y, upper=z)
#[1] TRUE TRUE FALSE TRUE TRUE TRUE
In base R, this is easier with comparison operators and is flexible
x >= y & x <= z
#[1] TRUE TRUE FALSE TRUE TRUE TRUE
data
x <- c(0.2, 0.2, 0.2, 0.5, 0.5, 0.5)
y <- c(0.0, 0.0, 0.0, 0.1, 0.052, -0.3)
z <- c(0.43, 0.52, 0.0, 0.76, 0.85, 0.83)

R: How can one rename columnname of 5 data.frames with 35 columns each at once?

I am using the below R code to simulate time series data, moving average of order 1 to be precise. I am varying 3 variables which are:
N = Number of elements in the series c(15L, 20L, 30L, 50L, 100L)
SD = standard deviation c(1, 2, 3, 4, 5) ^ 2
theta = the \theta value c(0.2, 0.4, 0.6, 0.8, 0.9, 0.95, 0.99)
I have 5 data.frames which you will see as .csv files in your R working directory. Each data.frame has 35 columns that I want properly labeled.
MWE
N <- c(15L, 20L, 30L, 50L, 100L)
SD = c(1, 2, 3, 4, 5) ^ 2
theta = c(0.2, 0.4, 0.6, 0.8, 0.9, 0.95, 0.99)
res <- vector('list', length(N))
names(res) <- paste('N', N, sep = '_')
set.seed(123L)
for (i in seq_along(N)){
res[[i]] <- vector('list', length(SD))
names(res[[i]]) <- paste('SD', SD, sep = '_')
ma <- matrix(NA_real_, nrow = N[i], ncol = length(theta))
for (j in seq_along(SD)){
wn <- rnorm(N[i], mean = 0, sd = SD[j])
ma[1:2, ] <- wn[1:2]
for (k in 3:N[i]){
ma[k, ] <- wn[k - 1L] * theta + wn[k]
}
colnames(ma) <- paste('ma_theta', theta, sep = '_')
res[[i]][[j]] <- ma
}
}
res1 <- lapply(res, function(dat) do.call(cbind, dat))
sapply(names(res1), function(nm) write.csv(res1[[nm]],
file = paste0(nm, ".csv"), row.names = FALSE, quote = FALSE))
I want columnname to be label not only with respect to theta alone but also with SD.
I want the columnname to be labelled like the below. I do not want 2 or more columns to have the same label. I want ma_SD_1... to (with theta=(0.2, 0.4, 0.6, 0.8, 0.9, 0.95, 0.99)) be exhausted before ma_SD_4... (with theta=(0.2, 0.4, 0.6, 0.8, 0.9, 0.95, 0.99)) before ma_SD_9... (with theta=(0.2, 0.4, 0.6, 0.8, 0.9, 0.95, 0.99)) before ma_SD_16... (with theta=(0.2, 0.4, 0.6, 0.8, 0.9, 0.95, 0.99)) before ma_SD_25... (with theta=(0.2, 0.4, 0.6, 0.8, 0.9, 0.95, 0.99)).
ma_SD_1_theta_0.2, ma_SD_1_theta_0.4, ma_SD_1_theta_0.6, ma_SD_1_theta_0.8, ma_SD_1_theta_0.9, ma_SD_1_theta_0.95, ma_SD_1_theta_0.99
ma_SD_4_theta_0.2, ma_SD_4_theta_0.4, ma_SD_4_theta_0.6, ma_SD_4_theta_0.8, ma_SD_4_theta_0.9, ma_SD_4_theta_0.95, ma_SD_4_theta_0.99
ma_SD_9_theta_0.2, ma_SD_9_theta_0.4, ma_SD_9_theta_0.6, ma_SD_9_theta_0.8, ma_SD_9_theta_0.9, ma_SD_9_theta_0.95, ma_SD_9_theta_0.99
ma_SD_1_theta_0.2, ma_SD_16_theta_0.4, ma_SD_16_theta_0.6, ma_SD_16_theta_0.8, ma_SD_16_theta_0.9, ma_SD_16_theta_0.95, ma_SD_16_theta_0.99
This should do it as you are iterating (using j) over the SD:
colnames(ma) <- paste('ma_SD',SD[j],'theta', theta, sep = '_')

Resources