Rowwise while loop over dataframe? - r

I have a function calculating something based on input variables, but I want to change the input variables depending on the result of the function. I feel that it is a very trivial question, but I have not found a working solution yet.
I have a dataset similar to this:
v1<-sample(5:12, 10, replace=T)
v2<-rep(100, 10)
v3<-rep(1,10)
v4<-sample(1:4, 10, replace=T)
t1<-sample(10:30, 10, replace=T)
And a function which uses the variables v1 to v4 to calculate something:
fun<-function(v1, v2, v3, v4){
#does complicated things
result<-((v2/(v1*v4))*v3
return(result)
}
out<-fun(v1, v2, v3, v4)
df<-data.frame(v1, v2, v3, v4, t1, out)
I need t1 < out. For non-vectorized data this seems to work:
while (out < t1){
v3= v3 + 1
out<- fun(v1, v2, v3, v4)
}
Ideally the last value for v3 is stored somehow.
v1 v1 v2 v3 v4 t1 out out_new v3_new
1 6 100 1 2 15 8.333333 16 2
2 12 100 1 2 17 4.166667 20 5
3 5 100 1 1 12 20.000000 20 1
4 10 100 1 4 26 2.500000 . .
5 8 100 1 2 15 6.250000 . .
6 6 100 1 3 18 5.555556
7 10 100 1 4 20 2.500000
8 11 100 1 2 12 4.545455
9 12 100 1 3 28 2.777778
10 6 100 1 2 25 8.333333
The output I am looking for is a dataframe looking like this:
What I am looking for is a vectorized solution that works on a large (100.000 rows) dataframe/tibble. I have tried different approaches with dplyr (mutate with case_when, ifelse) but have failed to come up with a working solution.

There is a way to achieve this using dplyr::rowwise():
library(tidyverse)
v1<-sample(5:12, 10, replace=T)
v2<-rep(100, 10)
v3<-rep(1,10)
v4<-sample(1:4, 10, replace=T)
t1<-sample(10:30, 10, replace=T)
fun<-function(v1, v2, v3, v4){
#does complicated things
result<-(v1/v2)*v4*v3
return(result)
}
reallyWeirdFunction = function(v1, v2, v3, v4, t){
out<- fun(v1, v2, v3, v4)
while (out < t){
v3= v3 + 1
out<- fun(v1, v2, v3, v4)
}
out
}
df<-data.frame(v1, v2, v3, v4, t1)
df %>%
rowwise() %>%
mutate(
out=fun(v1, v2, v3, v4),
out2=reallyWeirdFunction(v1, v2, v3, v4, t1)
)
#> # A tibble: 10 x 7
#> # Rowwise:
#> v1 v2 v3 v4 t1 out out2
#> <int> <dbl> <dbl> <int> <int> <dbl> <dbl>
#> 1 7 100 1 3 17 0.21 17.0
#> 2 11 100 1 2 24 0.22 24.2
#> 3 12 100 1 1 11 0.12 11.0
#> 4 10 100 1 4 15 0.4 15.2
#> 5 10 100 1 2 22 0.2 22
#> 6 9 100 1 1 16 0.09 16.0
#> 7 5 100 1 2 24 0.1 24
#> 8 12 100 1 2 23 0.24 23.0
#> 9 8 100 1 3 30 0.24 30
#> 10 7 100 1 2 14 0.14 14.
Created on 2020-08-28 by the reprex package (v0.3.0)
However, this is usually a very bad idea to use while loops in R, and rowwise() can be very slow in large datasets. You should definitely try to find a better algorithm than incrementing v3 like you are doing. I could not find one for your example though.

With mapply() and some other definitions you can do in base R:
set.seed(42)
df <- data.frame(v1=sample(5:12, 10, replace=T), v2=rep(100, 10), v3=rep(1,10),
v4=sample(1:4, 10, replace=T), t1=sample(10:30, 10, replace=T))
fun<-function(v1, v2, v3, v4) {
#does complicated things
result <- ((v2/(v1*v4))*v3)
return(result)
}
fun2 <- function(v1, v2, v3, v4, t) {
out <- fun(v1, v2, v3, v4)
while (out < t){
v3 <- v3 + 1
out <- fun(v1, v2, v3, v4)
}
return(list(v3new=v3, out=out))
}
cbind(df, t(mapply(fun2, df$v1, df$v2, df$v3, df$v4, df$t1)))
> cbind(df, t(mapply(fun2, df$v1, df$v2, df$v3, df$v4, df$t1)))
# v1 v2 v3 v4 t1 v3new out
# 1 5 100 1 3 24 4 26.66667
# 2 9 100 1 4 12 5 13.88889
# 3 5 100 1 3 18 3 20
# 4 5 100 1 4 13 3 15
# 5 6 100 1 1 14 1 16.66667
# 6 8 100 1 1 22 2 25
# 7 6 100 1 2 14 2 16.66667
# 8 6 100 1 4 29 7 29.16667
# 9 5 100 1 2 11 2 20
# 10 12 100 1 2 17 5 20.83333

Related

How can I create a df/dt where each column is the value of a row of an existing df/dt without loops?

I have a dataframe
data <- data.frame(v=c(15,25,24), x_val=c(12,7,2), y_val=c(6,6,18))
I want the resulting data to look like this with the data repeated in rows a specified number of times (here 2 times).
v1 x1 y1 v2 x2 y2 v3 x3 y3
15 12 6 25 7 6 24 2 18
15 12 6 25 7 6 24 2 18
I managed to get the data all in one row with the right column names but I'm not sure how to extend the column to a specified length with the values repeated. Further, how can I do this without loops? I want to run this with a larger dataset which can be quite slow with loops.
My code is below which gives the values in a single row.
r=NULL
r<- as.data.frame(matrix(nrow=1, ncol=1))
n<-2
for (i in 1:nrow(data_subset)){
datainarow <- data_subset[i,]
r=cbind(r,as.data.frame(datainarow))
colnames(r)[n] <- paste0("v",i)
colnames(r)[n+1] <- paste0("x",i)
colnames(r)[n+2] <- paste0("y",i)
n <- n+3
}
Thank you!
You can use uncount in the tidyr package
If you already have your data in the single row format, just do:
n=4
data %>% tidyr::uncount(n)
# A tibble: 4 x 9
v1 v2 v3 x1 x2 x3 y1 y2 y3
<dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 15 25 24 12 7 2 6 6 18
2 15 25 24 12 7 2 6 6 18
3 15 25 24 12 7 2 6 6 18
4 15 25 24 12 7 2 6 6 18
Here is one way to get that result from initial three row data frame
library(tidyverse)
n=4
data %>%
rename_all(~c("v","x","y")) %>%
mutate(id = row_number()) %>%
pivot_wider(names_from = id, values_from = v:y,names_sep = "") %>%
uncount(n)
This is a one-liner in base R
as.data.frame(t(as.vector(t(data))))[rep(1, 2),]
#> V1 V2 V3 V4 V5 V6 V7 V8 V9
#> 1 15 12 6 25 7 6 24 2 18
#> 1.1 15 12 6 25 7 6 24 2 18
Or if you wish to use the naming convention described, and have a more generalizable solution, you could use the following function:
expand_data <- function(data, reps) {
df <- as.data.frame(t(as.vector(t(data))))[rep(1, reps),]
names(df) <- paste(names(data), rep(seq(nrow(data)), each = nrow(data)), sep = "_")
rownames(df) <- NULL
df
}
which allows:
expand_data(data, 10)
v_1 x_val_1 y_val_1 v_2 x_val_2 y_val_2 v_3 x_val_3 y_val_3
1 15 12 6 25 7 6 24 2 18
2 15 12 6 25 7 6 24 2 18
3 15 12 6 25 7 6 24 2 18
4 15 12 6 25 7 6 24 2 18
5 15 12 6 25 7 6 24 2 18
6 15 12 6 25 7 6 24 2 18
7 15 12 6 25 7 6 24 2 18
8 15 12 6 25 7 6 24 2 18
9 15 12 6 25 7 6 24 2 18
10 15 12 6 25 7 6 24 2 18

find first occurrence in two variables in df

I need to find the first two times my df meets a certain condition grouped by two variables. I am trying to use the ddply function, but I am doing something wrong with the ".variables" command.
So in this example, I'm trying to find the first two times x > 30 and y > 30 in each group / trial.
The way I'm using ddply is giving me the first two times in the dataset, then repeating that for every group.
set.seed(1)
df <- data.frame((matrix(nrow=200,ncol=5)))
colnames(df) <- c("group","trial","x","y","hour")
df$group <- rep(c("A","B","C","D"),each=50)
df$trial <- rep(c(rep(1,times=25),rep(2,times=25)),times=4)
df[,3:4] <- runif(400,0,50)
df$hour <- rep(1:25,time=8)
library(plyr)
ddply(.data=df, .variables=c("group","trial"), .fun=function(x) {
i <- which(df$x > 30 & df$y >30 )[1:2]
if (!is.na(i)) x[i, ]
})
Expected results:
group trial x y hour
13 A 1 34.3511423 38.161134 13
15 A 1 38.4920710 40.931734 15
36 A 2 33.4233369 34.481392 11
37 A 2 39.7119930 34.470671 12
52 B 1 43.0604738 46.645491 2
65 B 1 32.5435234 35.123126 15
But instead, my code is finding c(1,4) from the first grouptrial and repeating that over for every grouptrial:
group trial x y hour
1 A 1 34.351142 38.161134 13
2 A 1 38.492071 40.931734 15
3 A 2 5.397181 27.745031 13
4 A 2 20.563721 22.636003 15
5 B 1 22.953286 13.898301 13
6 B 1 32.543523 35.123126 15
I would also like for there to be rows of NA if a second occurrence isn't present in a group*trial.
Thanks,
I think this is what you want:
library(tidyverse)
df %>% group_by(group, trial) %>% filter(x > 30 & y > 30) %>% slice(1:2)
Result:
# A tibble: 16 x 5
# Groups: group, trial [8]
group trial x y hour
<chr> <dbl> <dbl> <dbl> <int>
1 A 1 33.5 46.3 4
2 A 1 32.6 42.7 11
3 A 2 35.9 43.6 4
4 A 2 30.5 42.7 14
5 B 1 33.0 38.1 2
6 B 1 40.5 30.4 7
7 B 2 48.6 33.2 2
8 B 2 34.1 30.9 4
9 C 1 33.0 45.1 1
10 C 1 30.3 36.7 17
11 C 2 44.8 33.9 1
12 C 2 41.5 35.6 6
13 D 1 44.2 34.3 12
14 D 1 39.1 40.0 23
15 D 2 39.4 47.5 4
16 D 2 42.1 40.1 10
(slightly different from your results, probably a different R version)
I reccomend using dplyr or data.table rather than plyr. From the plyr github page:
plyr is retired: this means only changes necessary to keep it on CRAN
will be made. We recommend using dplyr (for data frames) or purrr (for
lists) instead.
Since someone has already provided a solution with dplyr, here is one option with data.table.
In the selection df[i, j, k] I am selecting rows which match your criteria in i, grouping by the given variables in k, and selecting the first two rows (head) of each group-specific subset of the data .SD. All of this inside the brackets is data.table specific, and only works because I converted df to a data.table first with setDT.
library(data.table)
setDT(df)
df[x > 30 & y > 30, head(.SD, 2), by = .(group, trial)]
# group trial x y hour
# 1: A 1 34.35114 38.16113 13
# 2: A 1 38.49207 40.93173 15
# 3: A 2 33.42334 34.48139 11
# 4: A 2 39.71199 34.47067 12
# 5: B 1 43.06047 46.64549 2
# 6: B 1 32.54352 35.12313 15
# 7: B 2 48.03090 38.53685 5
# 8: B 2 32.11441 49.07817 18
# 9: C 1 32.73620 33.68561 1
# 10: C 1 32.00505 31.23571 20
# 11: C 2 32.13977 40.60658 9
# 12: C 2 34.13940 49.47499 16
# 13: D 1 36.18630 34.94123 19
# 14: D 1 42.80658 46.42416 23
# 15: D 2 37.05393 43.24038 3
# 16: D 2 44.32255 32.80812 8
To try a solution that is closer to what you've tried so far we can do the following
ddply(.data=df, .variables=c("group","trial"), .fun=function(df_temp) {
i <- which(df_temp$x > 30 & df_temp$y >30 )[1:2]
df_temp[i, ]
})
Some explanation
One problem with the code that you provided is that you used df inside of ddply. So you defined fun= function(x) but you didn't look for cases of x> 30 & y> 30 in x but in df. Further, your code uses i for x, but i was defined with df. Finally, to my understanding there is no need for if (!is.na(i)) x[i, ]. If there is only one row that meets your condition, you will get a row with NAs anayway, because you use which(df_temp$x > 30 & df_temp$y >30 )[1:2].
Using dplyr, you can also do:
df %>%
group_by(group, trial) %>%
slice(which(x > 30 & y > 30)[1:2])
group trial x y hour
<chr> <dbl> <dbl> <dbl> <int>
1 A 1 34.4 38.2 13
2 A 1 38.5 40.9 15
3 A 2 33.4 34.5 11
4 A 2 39.7 34.5 12
5 B 1 43.1 46.6 2
6 B 1 32.5 35.1 15
7 B 2 48.0 38.5 5
8 B 2 32.1 49.1 18
Since everything else is covered here is a base R version using split
output <- do.call(rbind, lapply(split(df, list(df$group, df$trial)),
function(new_df) new_df[with(new_df, head(which(x > 30 & y > 30), 2)), ]
))
rownames(output) <- NULL
output
# group trial x y hour
#1 A 1 34.351 38.161 13
#2 A 1 38.492 40.932 15
#3 B 1 43.060 46.645 2
#4 B 1 32.544 35.123 15
#5 C 1 32.736 33.686 1
#6 C 1 32.005 31.236 20
#7 D 1 36.186 34.941 19
#8 D 1 42.807 46.424 23
#9 A 2 33.423 34.481 11
#10 A 2 39.712 34.471 12
#11 B 2 48.031 38.537 5
#12 B 2 32.114 49.078 18
#13 C 2 32.140 40.607 9
#14 C 2 34.139 49.475 16
#15 D 2 37.054 43.240 3
#16 D 2 44.323 32.808 8

Replace values in set of columns based on condition

I have a dataframe like this
id v1 v2 v3 v4 v5 pos
1 11 12 11 10 10 3
2 17 11 22 40 23 4
1 11 22 50 10 10 2
I would like to change its values based on a condition related to pos to get:
id v1 v2 v3 v4 v5 pos
1 11 12 12 12 12 3
2 17 11 22 22 22 4
1 11 11 11 11 11 2
So basically values get the previous value and the variable pos defines from where should we start.
Thx!
An approach using some indexing, which should be efficient in running time.
Not super efficient in terms of memory however, due to making a copy the same size as the input data:
vars <- paste0("v",1:5)
nv <- dat[vars][cbind(seq_len(nrow(dat)), dat$pos-1)]
ow <- col(dat[vars]) >= dat$pos
dat[vars][ow] <- nv[row(ow)[ow]]
# id v1 v2 v3 v4 v5 pos
#1 1 11 12 12 12 12 3
#2 2 17 11 22 22 22 4
#3 1 11 11 11 11 11 2
Explanation:
Get the variables of interest:
vars <- paste0("v",1:5)
Get the new values to overwrite for each row:
nv <- dat[vars][cbind(seq_len(nrow(dat)), dat$pos-1)]
Make a logical matrix of the cells to overwrite
ow <- col(dat[vars]) >= dat$pos
Overwrite the cells using a row identifier to pick the appropriate value.
dat[vars][ow] <- nv[row(ow)[ow]]
Quick comparative timing using a larger dataset:
dat <- dat[rep(1:3,1e6),]
# indexing
# user system elapsed
# 1.36 0.31 1.68
# apply
# user system elapsed
# 77.30 0.83 78.41
# gather/spread
# user system elapsed
# 293.43 3.64 299.10
Here is one idea with gather and spread.
library(tidyverse)
dat2 <- dat %>%
rowid_to_column() %>%
gather(v, value, starts_with("v")) %>%
group_by(rowid) %>%
mutate(value = ifelse(row_number() >= (pos - 1), nth(value, (pos - 1)[[1]]), value)) %>%
spread(v, value) %>%
ungroup() %>%
select(names(dat))
dat2
# # A tibble: 3 x 7
# id v1 v2 v3 v4 v5 pos
# <int> <int> <int> <int> <int> <int> <int>
# 1 1 11 12 12 12 12 3
# 2 2 17 11 22 22 22 4
# 3 1 11 11 11 11 11 2
DATA
dat <- read.table(text = "id v1 v2 v3 v4 v5 pos
1 11 12 11 10 10 3
2 17 11 22 40 23 4
1 11 22 50 10 10 2",
header = TRUE)
library(tidyverse)
Using apply from base R
data.frame(t(apply(df, 1, function(x)
c(x[1:x["pos"]], rep(x[x["pos"]], ncol(df) - x["pos"] - 2), x['pos']))))
# X1 X2 X3 X4 X5 X6
#1 1 11 12 12 12 3
#2 2 17 11 22 22 4
#3 1 11 11 11 11 2

How do I use dplyr to generate a new column based on rowwise data?

I want to add a new column to a data frame which is based on a row-wise calculation. Suppose I have a data frame such as this one:
x <-as.data.frame(matrix(1:10, 5, 2))
V1 V2
1 1 6
2 2 7
3 3 8
4 4 9
5 5 10
If I want to do some rowwise operation to generate a new column, I can use rowwise() and do() to accomplish that. For example:
y <- rowwise(x) %>% do (foo = .$V1 * .$V2)
I can even append this to the existing data frame as such:
y <- rowwise(x) %>% bind_cols(do (., foo = .$V1 * .$V2))
This all works, but the result isn't quite what I want. The values in y$foo are lists, not numeric.
V1 V2 foo
1 1 6 6
2 2 7 14
3 3 8 24
4 4 9 36
5 5 10 50
Looks right, but it isn't.
class(y$foo)
[1] "list"
So, two questions:
Is there a way to make the results numeric instead of lists?
Is there a better way I should be approaching this?
Update:
This is closer to what I am trying to do. Given this function:
pts <- 11:20
z <- function(x1, x2) {
min(x1*x2*pts)
}
This doesn't produce what I expect:
y <- x %>% mutate(foo = z(V1, V2))
V1 V2 foo
1 1 6 66
2 2 7 66
3 3 8 66
4 4 9 66
5 5 10 66
while this does:
y <-rowwise(x) %>% bind_cols( do (., data.frame(foo = z(.$V1, .$V2))))
V1 V2 foo
1 1 6 66
2 2 7 154
3 3 8 264
4 4 9 396
5 5 10 550
Why? Is there a better way?
I generally don't believe in row wise operations in a vectorized language such as R. In your case you could solve the question with a simple matrix multiplications.
You could define z as follows
z <- function(x1, x2) {
do.call(pmin, as.data.frame(tcrossprod(x1 * x2, pts)))
}
Than a simple mutate will do
x %>% mutate(foo = z(V1, V2))
# V1 V2 foo
# 1 1 6 66
# 2 2 7 154
# 3 3 8 264
# 4 4 9 396
# 5 5 10 550
You could also enhance performance using the matrixStats::rowMins function (which is fully vectorized)
library(matrixStats)
z <- function(x1, x2) {
rowMins(tcrossprod(x1 * x2, pts))
}
x %>% mutate(foo = z(V1, V2))
# V1 V2 foo
# 1 1 6 66
# 2 2 7 154
# 3 3 8 264
# 4 4 9 396
# 5 5 10 550
You should just return a data.frame in your do statement:
y <- rowwise(x) %>% bind_cols(do(., data.frame(foo = .$V1 * .$V2)))
y
## V1 V2 foo
## 1 1 6 6
## 2 2 7 14
## 3 3 8 24
## 4 4 9 36
## 5 5 10 50
y$foo
## [1] 6 14 24 36 50
In your updated question, you are missing the rowwise in the chain with the mutate statement, but have the rowwise in the chain with the do statement. Just add rowwise and you will get the same result.
x %>% rowwise %>% mutate(foo = z(V1, V2))
## Source: local data frame [5 x 3]
## Groups: <by row>
##
## V1 V2 foo
## 1 1 6 66
## 2 2 7 154
## 3 3 8 264
## 4 4 9 396
## 5 5 10 550
x <-as.data.frame(matrix(1:10, 5, 2))
foo <- apply(x , 1 , function(x){
prod(x)
})
#[1] 6 14 24 36 50
class(foo)
#[1] "numeric"
df_final <- cbind(x , foo)

Data Transformation in R for Panel Regression

I really need your help regarding a problem which may seem easy to solve for you.
Currently I work on a project which involves some panel-regressions. I have several large csv-files (up to 12 million entries per sheet) which are formatted as in the picture attached, whereas the columns (V1, V2) are individuals and the rows (1, 2, 3) are time identifiers.
In order to use the plm()-function I need all these files to convert to the following data structure:
ID Time X1 X2
1 1 x1 x2
1 2 x1 x2
1 ... ... ...
2 1 x1 x2
2 2 ... ...
I really struggle with this transformation and I'm really frustrated right now i.e. where do I get the identifier and the time index from?
Would really appreciate if you could provide me with information how to solve this problem.
If my question is not clear to you, just ask.
Best regards and thanks in advance
The output should look like as follows:
mydata<-structure(list(V1 = 10:13, V2 = 21:24, V3 = c(31L, 32L, 3L, 34L
)), .Names = c("V1", "V2", "V3"), class = "data.frame", row.names = c(NA,
-4L))
> mydata
V1 V2 V3
1 10 21 31
2 11 22 32
3 12 23 3
4 13 24 34
The following code can be used for your data without changing anything. For illustration, I used just the above data. I used the base R reshape function
long <- reshape(mydata, idvar = "time", ids = row.names(mydata),
times = names(mydata), timevar = "id",
varying = list(names(mydata)),v.names="value", new.row.names = 1:((dim(mydata)[2])*(dim(mydata)[1])),direction = "long")
> long
id value time
1 V1 10 1
2 V1 11 2
3 V1 12 3
4 V1 13 4
5 V2 21 1
6 V2 22 2
7 V2 23 3
8 V2 24 4
9 V3 31 1
10 V3 32 2
11 V3 3 3
12 V3 34 4
long$id<-substr(long$id,2,4) # 4 is used to take into account your 416 variables
myout<-long[,c(1,3,2)]
> myout
id time value
1 1 1 10
2 1 2 11
3 1 3 12
4 1 4 13
5 2 1 21
6 2 2 22
7 2 3 23
8 2 4 24
9 3 1 31
10 3 2 32
11 3 3 3
12 3 4 34
Here is an alternative: Use Stacked from my "splitstackshape" package.
Here it is applied on #Metrics's sample data:
# install.packages("splitstackshape")
library(splitstackshape)
Stacked(cbind(id = 1:nrow(mydata), mydata),
id.vars="id", var.stubs="V", sep = "V")
# id .time_1 V
# 1: 1 1 10
# 2: 1 2 21
# 3: 1 3 31
# 4: 2 1 11
# 5: 2 2 22
# 6: 2 3 32
# 7: 3 1 12
# 8: 3 2 23
# 9: 3 3 3
# 10: 4 1 13
# 11: 4 2 24
# 12: 4 3 34
It would be very fast if your data are large. Here are the speeds for the 12MB dataset you linked to. The sorting is different but the data are the same.
It still isn't faster than stack though (but at some point, stack starts to slow down).
See the system.times below:
reshape()
system.time(out <- reshape(x, idvar = "time", ids = row.names(x),
times = names(x), timevar = "id",
varying = list(names(x)),
v.names="value",
new.row.names = 1:prod(dim(x)),
direction = "long"))
# user system elapsed
# 53.11 0.00 53.11
head(out)
# id value time
# 1 V1 0.003808635 1
# 2 V1 -0.018807416 2
# 3 V1 0.008875447 3
# 4 V1 0.001148695 4
# 5 V1 -0.019365004 5
# 6 V1 0.012436560 6
Stacked()
system.time(out2 <- Stacked(cbind(id = 1:nrow(x), x),
id.vars="id", var.stubs="V",
sep = "V"))
# user system elapsed
# 0.30 0.00 0.29
out2
# id .time_1 V
# 1: 1 1 0.003808635
# 2: 1 10 -0.014184635
# 3: 1 100 -0.013341843
# 4: 1 101 0.006784138
# 5: 1 102 0.006463707
# ---
# 963868: 2317 95 0.009569451
# 963869: 2317 96 0.002497771
# 963870: 2317 97 0.009202519
# 963871: 2317 98 0.017007545
# 963872: 2317 99 -0.002495842
stack()
system.time(out3 <- cbind(id = 1:nrow(x), stack(x)))
# user system elapsed
# 0.09 0.00 0.09
head(out3)
# id values ind
# 1 1 0.003808635 V1
# 2 2 -0.018807416 V1
# 3 3 0.008875447 V1
# 4 4 0.001148695 V1
# 5 5 -0.019365004 V1
# 6 6 0.012436560 V1

Resources