Skip to content

Suggested convenient function: move column order #4668

Closed

Description

@dracodoc

In my daily development I wrote some convenient functions. There is nothing fancy in them, but I feel they are quite useful in data analysis. So I'm wondering if they can be useful to others and be included as a part of data.table.

move column order

I may generate some new column and it will be located at the end of the table. I want to move it to around the relevant columns so it's easier to compare/investigate them. It's hard to write a full column order vector for this manually, nor will the "move some columns to front" option in setcolorder help on this.

move_cols <- function(dt, cols_to_move, position = "after", anchor) {
  stopifnot(position %in% c("before", "after"))
  # we always split columns without the moving subset into left, anchor, right, then insert the moving subset before or after anchor
  original_cols <- names(dt)
  anchor_location <- which(original_cols == anchor)
  left_cols <- setdiff(original_cols[1:(anchor_location - 1)], cols_to_move)
  right_cols <- setdiff(original_cols[(anchor_location + 1):length(original_cols)], cols_to_move)
  new_cols <- switch(position,
                     before = c(left_cols, cols_to_move, anchor, right_cols),
                     after =  c(left_cols, anchor, cols_to_move, right_cols))
  setcolorder(dt, new_cols)
}
dt <- data.table(mtcars)
# note the parameter order is easy to read
move_cols(dt, "wt", "after", "disp")[]

Activity

  1. ColeMiller1 commented on Aug 10, 2020

    @ColeMiller1
    Contributor

    Same as #4358?

  2. dracodoc commented on Aug 10, 2020

    @dracodoc
    ContributorAuthor

    Yes this is the same request. Glad to see similar request.
    Mine has the implementation done as a simple wrapper on setcolorder. Adding parameter to setcolorder is another possible interface.

    My implementation though is name based, as I prefer to use column name which is more robust to change in data. In this aspect adding parameter to setcolorder may means it need to support column index, which need another implementation (the idea is similar and simple). I'd love to implement it too if needed.

  3. ColeMiller1 commented on Aug 11, 2020

    @ColeMiller1
    Contributor

    Would you mind closing this and adding to the other issue? There may be more input on API - mainly move_cols(dt, "wt", "after", "disp") vs. setcolorder(dt, "wt", .after = "disp"). The implementation could be similar to what you provided.

    My implementation though is name based, as I prefer to use column name which is more robust to change in data.

    setcolorder accepts integer or character vectors - the other FR would need to support it as well.

  4. mrdwab commented on Aug 11, 2020

    @mrdwab

    @dracodoc Just a heads up: I think you need to modify your function for cases when you're moving before the first column or after the last column:

    > move_cols(dt, "vs", "before", "mpg")[]
    Error in colnamesInt(x, neworder, check_dups = TRUE) : 
      argument specifying columns specify duplicated column(s)
    > move_cols(dt, "vs", "after", "carb")[]
    Error in colnamesInt(x, neworder, check_dups = TRUE) : 
      argument specifying columns specify non existing column(s): cols[12]='NA'

    Also, just for fun, there's also my moveMe function that can easily be modified to work like move_cols with setcolorder. It doesn't work with values with spaces though--something I've been meaning to work on.

  5. jangorecki commented on Aug 11, 2020

    @jangorecki
    Member

    Better new arg than new function

  6. dracodoc commented on Aug 11, 2020

    @dracodoc
    ContributorAuthor

    @dracodoc Just a heads up: I think you need to modify your function for cases when you're moving before the first column or after the last column:

    > move_cols(dt, "vs", "before", "mpg")[]
    Error in colnamesInt(x, neworder, check_dups = TRUE) : 
      argument specifying columns specify duplicated column(s)
    > move_cols(dt, "vs", "after", "carb")[]
    Error in colnamesInt(x, neworder, check_dups = TRUE) : 
      argument specifying columns specify non existing column(s): cols[12]='NA'

    Also, just for fun, there's also my moveMe function that can easily be modified to work like move_cols with setcolorder. It doesn't work with values with spaces though--something I've been meaning to work on.

    Yes, thanks for pointing out this. I often feel R's treatment for indexing is not optimal in these cases, i.e vec[1:0] should just return NULL then everything will be fine.

    If there is a plan to add the feature to setcolorder, I'd love to implement a PR for review, including the first/last bug fixed, and supporting column index.

  7. dracodoc commented on Aug 11, 2020

    @dracodoc
    ContributorAuthor

    I created a PR at #4669.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions