假设我在data.table中有这样的列:
很抱歉,我第一次没有具体说明。每个值都属于一个项目代码。代码将重复几次,因为这些项属于一个系列。有些项目的值为a,b,c
,有些项目为a,b,c,d
,有些项目为a,b
,有些项目只有b
。
family item value
1 001 01 a
2 001 01 b
3 001 01 c
4 001 02 b
5 001 05 b
6 001 32 a
7 001 32 b
8 001 32 c
9 001 32 d
10 002 01 a
11 002 01 b
12 002 01 c
13 002 32 b
14 002 55 b
如何通过将b
放在每个项目的前面来订购列?例如b,a,c
,b,a,c,d
,b,a
,b
。有序列应如下所示:
family item value id
1 001 01 b 1
2 001 01 a 1
3 001 01 c 1
4 001 02 b 2
5 001 05 b 3
6 001 32 b 4
7 001 32 a 4
8 001 32 c 4
9 001 32 d 4
10 002 01 b 5
11 002 01 a 5
12 002 01 c 5
13 002 32 b 6
14 002 55 b 7
data.table包有setorder()和setorderv(),但两者都只能按列排序。特定值怎么样?
答案 0 :(得分:5)
假设您的data.table
被称为“DT”且列名称为“V1”和“V2”,请尝试以下操作:
DT[, V2 := factor(V2, c("b", setdiff(unique(V2), "b")))][order(V1, V2)]
# V1 V2
# 1: 1 b
# 2: 1 a
# 3: 1 c
# 4: 2 b
# 5: 3 b
# 6: 4 b
# 7: 4 a
# 8: 4 c
# 9: 4 d
使用新的样本数据,尝试以下方法:
DT[, id := .GRP, by = list(family, item)][, value := factor(
value, c("b", setdiff(unique(value), "b")))][order(id, value)]
# family item value id
# 1: 1 1 b 1
# 2: 1 1 a 1
# 3: 1 1 c 1
# 4: 1 2 b 2
# 5: 1 5 b 3
# 6: 1 32 b 4
# 7: 1 32 a 4
# 8: 1 32 c 4
# 9: 1 32 d 4
# 10: 2 1 b 5
# 11: 2 1 a 5
# 12: 2 1 c 5
# 13: 2 32 b 6
# 14: 2 55 b 7
上面的答案很好(更一般)。在这种特殊情况下,我们也可以这样做。我们只需创建一个整数列,其b
的值较小,然后使用setorder
按引用对行重新排序,如下所示:
DT[, id := 1L][value == "b", id := 0L]
setorder(DT, family, item, id)[, id := NULL] # don't need 'id' after ordering
# family item value
# 1: 1 1 b
# 2: 1 1 a
# 3: 1 1 c
# 4: 1 2 b
# 5: 1 5 b
# 6: 1 32 b
# 7: 1 32 a
# 8: 1 32 c
# 9: 1 32 d
# 10: 2 1 b
# 11: 2 1 a
# 12: 2 1 c
# 13: 2 32 b
# 14: 2 55 b