在R中的相关列之间有效地交换值

yr9zkbsy  于 2023-10-13  发布在  其他
关注(0)|答案(1)|浏览(107)

我有一个dataframe,看起来像这样:

example <- data.frame(
  date = as.Date(c('2001-01-01',
                   '2001-01-02',
                   '2001-01-01',
                   '2001-01-02')),
  PID_A = c(1091, 1091, 1037, 1037),
  PID_B = c(2091, 2091, 2037, 2037),
  resp_A = c(3,1,2,4),
  resp_B = c(2,4,3,1),
  connect_A = c(6,2,5,3),
  connect_B = c(5,3,6,2),
  test_A = c(3,9,0,0),
  test_B = c(1,1,1,1)
)

我想交换相关列之间的值,这样X_A现在是X_B,X_B现在是X_A。我想在所有列上执行此操作,并将_A和_B附加到列名**,但**PID_A和PID_A除外(例如,仅respconnecttest)。实际上,我有更多这样的列,但为了举例,我将数据集简化为这三个变量。
有没有一个有效的方法来做到这一点?
这是所需的输出:

example_solution <- data.frame(
  date = as.Date(c('2001-01-01',
                   '2001-01-02',
                   '2001-01-01',
                   '2001-01-02')),
  PID_A = c(1091, 1091, 1037, 1037),
  PID_B = c(2091, 2091, 2037, 2037),
  resp_A = c(2,4,3,1),
  resp_B = c(3,1,2,4),
  connect_A = c(5,3,6,2),
  connect_B = c(6,2,5,3),
  test_A = c(1,1,1,1),
  test_B = c(3,9,0,0)
)
klsxnrf1

klsxnrf11#

我认为最有效的方法是更改列名,而不是乱处理数据。
我们可以使用stringr::str_replace(),我们可以提供一个函数,而不是一个固定的替代品。该函数会说:如果列名以"_A"结尾,则使其以"_B"结尾,反之亦然(除非名称以"PID"开头)。

col_order <- names(example) # In case you need to preserve order
names(example) <- stringr::str_replace(
    names(example),
    "(?<!^PID)_[AB]$",
    \(x) ifelse(x == "_A", "_B", "_A")
)

如果列顺序很重要,您可以切换回原始顺序。这不会创建数据的副本。

example  <- example[col_order]
#         date PID_A PID_B resp_A resp_B connect_A connect_B test_A test_B
# 1 2001-01-01  1091  2091      2      3         5         6      1      3
# 2 2001-01-02  1091  2091      4      1         3         2      1      9
# 3 2001-01-01  1037  2037      3      2         6         5      1      0
# 4 2001-01-02  1037  2037      1      4         2         3      1      0

正则表达式模式说明

我们可以使用negative lookbehind来匹配所有以"_A""_B"结尾的列名,除非前面紧跟着字符串的开头,后面跟着"PID"

Regex visualiser

相关问题