plagueheart
plagueheart

Reputation: 239

r - Force which() to return only first match

Part of a function I'm working on uses the following code to take a data frame and reorder its columns on the basis of the largest (absolute) value in each column.

ord <- order(abs(apply(dfm,2,function(x) x[which(abs(x) == max(abs(x)), arr.ind = TRUE)])))

For the most part, this works fine, but with the dataset I'm working on, I occasionally get data that looks like this:

a <- rnorm(10,5,7); b <- rnorm(10,0,1); c <- rep(1,10)
dfm <- data.frame(A = a, B = b, C = c)

> dfm
         A          B     C
1    0.6438373 -1.0487023 1
2   10.6882204  0.7665011 1
3  -16.9203506 -2.5047946 1
4   11.7160291 -0.1932127 1
5   13.0839793  0.2714989 1
6   11.4904625  0.5926858 1
7   -5.9559206  0.1195593 1
8    4.6305924 -0.2002087 1
9   -2.2235623 -0.2292297 1
10   8.4390810  1.1989515 1

When that happens, the above code returns a "non-numeric argument to mathematical function" error at the abs() step. (And if I get rid of the abs() step because I know, due to transformation, my data will be all positive, order() returns: "unimplemented type 'list' in 'orderVector1'".) This is because which() returns all the 1's in column C, which in turn makes apply() spit out a list, rather than a nice tidy vector.

My question is this: How can I make which() JUST return one value for column C in this case? Alternately, is there a better way to write this code to do what I want it to (reorder the columns of a matrix based on the largest value in each column, whether or not that largest value is duplicated) that won't have this problem?

Upvotes: 2

Views: 4740

Answers (2)

Frank
Frank

Reputation: 66819

To order the columns by their maximum element (in absolute value), you can do

dfm[order(apply(abs(dfm),2,max))]

Your code, with @CarlosCinelli's correction, should work fine, though.

Upvotes: 2

Carlos Cinelli
Carlos Cinelli

Reputation: 11607

If you want to select just the first element of the result, you can subset it with [1]:

ord <- order(abs(apply(dfm,2,function(x) x[which(abs(x) == max(abs(x)), arr.ind = TRUE)][1])))

Upvotes: 3

Related Questions