我有一个如下所示的数据框:
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(例如,仅 resp
、connect
、 测试
)。实际上,我有更多这样的列,但为了举例,我已将数据集简化为这三个变量。
有没有有效的方法来做到这一点?
这是所需的输出:
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)
)
最佳答案
我认为最有效的方法是更改列名称,而不是弄乱数据。
我们可以使用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"
.
关于r - 在 R 中的相关列之间高效交换值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/77240071/