[R] Reformatting a table

Marc Schwartz marc_schwartz at comcast.net
Thu Nov 20 23:01:14 CET 2008


on 11/20/2008 02:28 PM Tul Gan wrote:
> Hi !
> ���������� I am new to R. Can somebody help me in reformatting�huge output files ,i.e, rearranging sets of columns in specific order.
> For example: I have data for three compunds 1, 2 and 3
> file1:
> ID CA1 CA3 CA2 MA2 MA1 MA3 
> 1 14 15 13 7 12 3 
> 2 19 7 12 10 14 5 
> 3 21 12 19 6 8 9 
>> to 
> File 2:
>> ID CA1 CA2 CA3 MA1 MA2 MA3 
> 1 14 13 15 12 7 3 
> 2 19 12 7 14 10 5 
> 3 21 19 12 8 6 9 
>> or File3:
> ID CA1 MA1 CA2 MA2 CA3 MA3 
> 1 14 12 13 7 15 3 
> 2 19 14 12 10 7 5 
> 3 21 8 19 6 12 9 
>> Thanks for your help,
> Tul Gan


A general approach to the first case, where 'DF' is the initial data frame:

> DF[, c("ID", sort(names(DF)[-1]))]
  ID CA1 CA2 CA3 MA1 MA2 MA3
1  1  14  13  15  12   7   3
2  2  19  12   7  14  10   5
3  3  21  19  12   8   6   9


Essentially, you are sorting the column names less "ID", then reordering
the columns of 'DF' using indexing.

> names(DF)[-1]
[1] "CA1" "CA3" "CA2" "MA2" "MA1" "MA3"

> sort(names(DF)[-1])
[1] "CA1" "CA2" "CA3" "MA1" "MA2" "MA3"



The second case is a little more complicated, since you are
independently sorting on both alpha and numeric values, rather than just
 alpha.

If there is a predictable sequence of names, you could do something like:

> paste(c("CA", "MA"), rep(1:3, each = 2), sep = "")
[1] "CA1" "MA1" "CA2" "MA2" "CA3" "MA3"

Thus:

> DF[, c("ID", paste(c("CA", "MA"), rep(1:3, each = 2), sep = ""))]
  ID CA1 MA1 CA2 MA2 CA3 MA3
1  1  14  12  13   7  15   3
2  2  19  14  12  10   7   5
3  3  21   8  19   6  12   9


If the sequence is not predictable, such that you would generate
non-existing column names with the above, then we need to split the
existing column names and sort them separately. Something along the
lines of the following:

# use gsub() to split out the alpha and numeric values. Note that we
# need to create a data frame to handle an alpha and a numeric column

names.df <- data.frame(Alpha = gsub("[[:digit:]]", "",
                                    names(DF)[-1]),
                       Digits = as.numeric(gsub("[[:alpha:]]", "",
                                                names(DF)[-1])))


> names.df
  Alpha Digits
1    CA      1
2    CA      3
3    CA      2
4    MA      2
5    MA      1
6    MA      3


Now, get the indices for the sorted rows, based first upon the digits
value, subsorted by the Alpha value:

> order(names.df$Digits, names.df$Alpha)
[1] 1 5 3 4 2 6

Now use those values to index the columns in 'DF'. Remember that we need
to add 1 to each index, to account for the "ID" column, which is not
included in 'names.mat':

> c(1, order(names.df$Digits, names.df$Alpha) + 1)
[1] 1 2 6 4 5 3 7

Thus:

> DF[, c(1, order(names.df$Digits, names.df$Alpha) + 1)]
  ID CA1 MA1 CA2 MA2 CA3 MA3
1  1  14  12  13   7  15   3
2  2  19  14  12  10   7   5
3  3  21   8  19   6  12   9


Note, that we could also solve the first case, by reversing the sorting
levels from names.df:

> DF[, c(1, order(names.df$Alpha, names.df$Digits) + 1)]
  ID CA1 CA2 CA3 MA1 MA2 MA3
1  1  14  13  15  12   7   3
2  2  19  12   7  14  10   5
3  3  21  19  12   8   6   9

See ?gsub, ?sort and ?order

HTH,

Marc Schwartz



More information about the R-help mailing list