1

I have a data which is a m*n matrix. I would like to split the matrix by column and save each column separately in a different vector. E.g

data<-matrix(1:9, ncol=3)

I would like to have vec1 containing the first column so

vec1 will be transpose of [1,2,3], a column matrix with dimension 3*1 which is basically the first column of data. Similarly, vec2 represents the 2nd column and vec3 represents the last column.

I understand that I can do this manually by repeating

vec1<-data[,1], 
vec2<-data[,2] 
... 
vecn<-data[,n]. 

However, this is not feasible when n is large. So I would like to know whether it is feasible to use a loop to do this.

user20650
  • 21,689
  • 5
  • 46
  • 77
  • 1
    Welcome to StackOverflow! Please read the info about [how to ask a good question](http://stackoverflow.com/help/how-to-ask) and how to give a [reproducible example](http://stackoverflow.com/questions/5963269). This will make it much easier for others to help you. – Sotos Jan 08 '18 at 14:39
  • This is a pretty terrible idea - sequentially named variables are much harder to work with than, say, a nice matrix. They don't scale well, they often lead to copy/paste and find/replace with bugs caused by typos.... Why do you want to do this? What is the bigger problem? Using a `list` is a nice way to keep them in a single object in case a matrix isn't suitable. You might want to read [How do I make a list of data frames](https://stackoverflow.com/questions/17499013/how-do-i-make-a-list-of-data-frames/24376207#24376207) for related discussion. – Gregor Thomas Jan 08 '18 at 15:24
  • @Gregor Thanks for your comment. I am working on a project in determining the position of an object in the next second using the data of the previous 10 seconds. The position of the object is determined by 10 joints and each joint has 3 coordinates. Therefore, I need to make predictions for all 30 coordinates in order to get the prediction. So what I intended to do is to use 30 variables to represent 30 coordinates and loop all the processes from data cleansing to modelling. – user9184644 Jan 08 '18 at 17:22
  • 1
    I think the structure of your code will be much easier if you use a single matrix or a single list to hold all 30 coordinates. Looping over columns of a matrix is highly optimized using the `apply` function - you will add complexity to your code and lose efficiency by taking variables out of a matrix. `data.frames` are particularly slow when compared to matrices. – Gregor Thomas Jan 08 '18 at 17:38
  • And, I should add, that even if you need them as data frames to plug into some other function, you can just do `apply(your_matrix, 2, function(x) other_function(data.frame(X1 = x)))` without cluttering your workspace with `n` single-column data frames. – Gregor Thomas Jan 08 '18 at 17:50

1 Answers1

0

As has been pointed out, this is probably not a good idea. However, if you still felt the need to proceed down this path, rather than using a list or just using the source matrix itself, the easiest approach would probably be to use a combination of list2env and data.frame.

Here's a demo, step-by-step:

data <- matrix(1:9, ncol=3)

ls()  # Only one object in my workplace
# [1] "data"

data_list <- unclass(data.frame(data))
str(data_list)
# List of 3
#  $ X1: int [1:3] 1 2 3
#  $ X2: int [1:3] 4 5 6
#  $ X3: int [1:3] 7 8 9
#  - attr(*, "row.names")= int [1:3] 1 2 3

ls() # Two objects now
# [1] "data"      "data_list"

list2env(data_list, envir = .GlobalEnv)

ls() # Five objects now
# [1] "data"      "data_list" "X1"        "X2"        "X3"  

X1
# [1] 1 2 3

If you want single-column data.frames, you can use split.list:

list2env(setNames(split.default(data.frame(data), seq(ncol(data))), 
                  paste0("var", seq(ncol(data)))), envir = .GlobalEnv)
var1
#   X1
# 1  1
# 2  2
# 3  3

Putting this together, you can actually do this all at once (without first having to create "data_list") like this:

list2env(data.frame(data), envir = .GlobalEnv)

But again, you should have a good reason to do so!

A5C1D2H2I1M1N2O1R2T1
  • 177,446
  • 27
  • 370
  • 450