13

I need to create a data.frame that will be populated one row at a time by results of a for loop. It has 45 columns: the names of five of these are static but the remainder are read in (as a vector) from an external CSV file at run time. I'm looking for something along the lines of

goalsMenu <- read.csv("Phase 1 goalsmenu.csv", header = TRUE)
colHeads <- c("analysis","patient","date",as.vector(goalsMenu$Name),"CR")
output <- data.frame(colHeads)

however this creates a one-column data.frame with column name of colHeads.

colHeads <- list("analysis","patient","date",as.vector(goalsMenu$Name),"CR")

seems a step in the right direction but I need to "flatten" it to create the desired data.frame structure

could you advise please?

Rob Forsyth
  • 155
  • 1
  • 1
  • 5

3 Answers3

10

Does this help?

goalsMenu <- paste("Name", 1:40, sep="")
output <- as.data.frame(matrix(rep(0, 5 + length(goalsMenu)), nrow=1))
names(output) <- c("analysis", "patient", "date", goalsMenu, "CR1", "CR2")

Basically, I create a data.frame output with the number of columns first and name those columns in the next step. However, be aware about mdsumner's comment! This way, all columns are of class numeric. You can deal with that later though: change the class of columns in data.frame

Community
  • 1
  • 1
Christoph_J
  • 6,804
  • 8
  • 44
  • 58
  • Thanks - this has worked (although have to strip out the first all-zero row afterwards). With the exception (as you would expect) of date all columns are numeric (the first two integer reference numbers; the rest all float) – Rob Forsyth Apr 03 '12 at 11:31
  • @RobForsyth Since you said that you are looping through rows anyways to fill up that data.frame, I think you just have to start with row one and replace the zeros there. Also, this should automatically overwrite the column class. Is your question answered then? Or are you looking for something else? In case it's the former, it would be good if you could accept mine or Allan's answer, so this one is off-list. Otherwise, it would be great if you could give more details and I could give it another try ;-) Or maybe someone else has a better solution (I guess there is one). – Christoph_J Apr 03 '12 at 12:40
  • sorry - new to Stackoverflow etiquette! Now marked answered: thanks again! – Rob Forsyth Apr 03 '12 at 13:23
  • No worries, took my a while to get used to SO as well. Welcome on board and glad I could help... – Christoph_J Apr 03 '12 at 14:51
6

If you can fill the frame with (some) data first, then you can just assign to names(). Otherwise, you'll have to make the list first (and then later convert to data.frame):

col.names <- LETTERS[1:10]  # Example column names
data <- vector("list", length(col.names))
names(data) <- col.names
print(str(data))            # Inspect the structure

Hope this helps

Allan Engelhardt
  • 1,421
  • 10
  • 5
1
for (k in c(1:length(names_array))) {
   #Let's make a blank column, that's the length of the data frame that I'm 
   #going to attach it to:

   temp_col<-rep(NA, nrow(my_df))

   # now here's our 2nd loop
   for(i in c(1:nrow(my_df))) {
      #process the col with some stuff
       temp_col[i] <- i
    } 

    # now we're going to attach the column to the last column in the data 
    #frame
    my_df$temp_col<-temp_col

    # now we're going to assign the name from a vector 
    # we do this by looking at the length of the names
    # array, and use that as the index
    names(my_df)[length(names(my_df))]<-names_array[k]
}