如何使用 R 交换 data.table 中的列值
Posted
技术标签:
【中文标题】如何使用 R 交换 data.table 中的列值【英文标题】:How to swap column values in a data.table using R 【发布时间】:2022-01-18 22:36:20 【问题描述】:我有下面给出的玩具数据。
library(data.table)
(tmp <- data.table(R1 = c('D','D','D','T','C'), y = 10:1, R2 = c('D','A','Z','D','D')))
R1 y R2
1: D 10 D
2: D 9 A
3: D 8 Z
4: T 7 D
5: C 6 D
6: D 5 D
7: D 4 A
8: D 3 Z
9: T 2 D
10: C 1 D
我想交换 R1
和 R2
列中的值,以便所有 A
都列在 R1 下,而不常见的值则转到 R2。有人可以告诉我怎么做吗?
这是所需的输出。
R1 y R2
1: D 10 D
2: D 9 A
3: D 8 Z
4: D 7 T
5: D 6 C
6: D 5 D
7: D 4 A
8: D 3 Z
9: D 2 T
10: D 1 C
这是下面提供的答案的性能结果 -
Unit: milliseconds
expr min lq mean median uq max neval cld
akrun 5.524562 5.587740 7.526681 5.605406 5.938955 14.976740 5 b
r2evans 1.466862 1.489944 1.509321 1.500263 1.536402 1.553134 5 a
【问题讨论】:
如果你只需要D
,为什么不能是tmp[, R1 := "D"]
我不想丢失R1
中的值,并希望将它们转移到R2
,同时将R1
替换为D
。
对造成混乱表示歉意。我在之前的专栏中选择了有趣的专栏A
,pmin
和pmax
工作得很好。但是当我在A to Z
之间给出一个字母时,解决方案失败了。
基于您的新数据。我认为tmp[R2 == "D", c("R1", "R2") := .(R2, R1)]
是的,这个解决方案有效并且看起来更直观。你能回答吗?我不确定交换是否更早发生或R2
首先被D
替换?
【参考方案1】:
根据更新,我们可以在i
上指定一个逻辑表达式并交换列值以分配
library(data.table)
val <- "D"
tmp[R2 == val, c("R1", "R2") := .(R2, R1)]
-输出
> tmp
R1 y R2
1: D 10 D
2: D 9 A
3: D 8 Z
4: D 7 T
5: D 6 C
6: D 5 D
7: D 4 A
8: D 3 Z
9: D 2 T
10: D 1 C
【讨论】:
是的,这很好:它是规范的,可能更快,也更清晰。 (它也可以很容易地使用我的interesting
-set 前提,同时替换fifelse
s 等。很好。)
这个解决方案现在就像一个魅力,而且非常直观。谢谢@akrun。您能否解释一下为什么先发生列中的交换,然后将R2
替换为val
?
您能否解释一下为什么先发生列中的交换,然后将R2
替换为val
?我想知道事件序列是如何执行的。
R2
没有被val
替换; R2 == val
是条件,因此只有符合该条件的行才会交换值。
@Saurabh 当您执行 tmp[R2 == val]
时,它仅对那些 R2 值为“D”的行的数据进行子集化,在 j
中,我们只是将列值交换到 R1 , R2 或反之【参考方案2】:
我怀疑另一个答案可能是最适用的,但如果您的需求不是基于字典排序(实际上只是存在于一组“有趣”值中),那么
interesting <- c("A")
tmp[, c("R1", "R2") := .(
fifelse(R2 %in% interesting & !R1 %in% interesting, R2, R1),
fifelse(R2 %in% interesting & !R1 %in% interesting, R1, R2))]
tmp
# x R1 R2
# <int> <char> <char>
# 1: 1 A A
# 2: 2 A F
# 3: 3 A T
# 4: 4 A G
# 5: 5 A I
# 6: 6 A A
# 7: 7 A F
# 8: 8 A T
# 9: 9 A G
# 10: 10 A I
我承认这看起来有点笨拙,重复计算条件。这可以作为tmp
框架内部或外部的临时变量轻松更有效地工作,例如:
tmp[, swap := R2 %in% interesting & !R1 %in% interesting
][, c("R1", "R2") := .(fifelse(swap, R2, R1), fifelse(swap, R1, R2))
][, swap := NULL]
如果您确定 R2 %in% interesting
与 !R2 %in% interesting
完全一致(也就是说,R1
和 R2
绝不是有趣,...或如果两者都很有趣,您不关心交换,如第 1 行和第 6 行),那么您可以将其简化为
tmp[, c("R1", "R2") := .(
fifelse(R2 %in% interesting, R2, R1),
fifelse(R2 %in% interesting, R1, R2))]
【讨论】:
谢谢,@r2evans。我稍微改变了问题并将D
设置为interesting
值而不是A
。您的解决方案也适用于这种情况。
我很高兴它对你有用。 y
的添加似乎并没有任何效果,我的答案中是否缺少某些内容?
您的解决方案要快得多。我已经分享了上面的表现。
说实话,这很令人惊讶。以上是关于如何使用 R 交换 data.table 中的列值的主要内容,如果未能解决你的问题,请参考以下文章
如何根据一个数据帧中的列值和R中另一个数据帧的列标题名称有条件地创建新列
在 R 中,自定义由 dcast.data.table 创建的列的名称