根据其他两列(纬度、经度)中的值添加唯一 ID 列
Add unique ID column based on values in two other columns (lat, long)
有人问过这个问题,但我正在寻找更完整的 answer/slightly 修改后的输出。
我有一个数据集,其中 Lat 和 Long 值位于不同的列中,我想为 Lat 和 Long 的每个唯一组合创建一个唯一 ID。
我将从较旧的 post 那里借用一个示例数据集来问同样的问题,但我需要一个稍微不同的解决方案 (Add ID column by group)。
d <- read.table(text='LAT LONG
13.5330 -15.4180
13.5330 -15.4180
13.5330 -15.4180
13.5330 -15.4180
13.5330 -15.4170
13.5330 -15.4170
13.5330 -15.4170
13.5340 -14.9350
13.5340 -14.9350
13.5340 -15.9170
13.3670 -14.6190', header=TRUE)
给出的解决方案是:
d <- transform(d, Cluster_ID = as.numeric(interaction(LAT, LONG, drop=TRUE)))
# LAT LONG Cluster_ID
# 1 13.533 -15.418 2
# 2 13.533 -15.418 2
# 3 13.533 -15.418 2
# 4 13.533 -15.418 2
# 5 13.533 -15.417 3
# 6 13.533 -15.417 3
# 7 13.533 -15.417 3
# 8 13.534 -14.935 4
# 9 13.534 -14.935 4
# 10 13.534 -15.917 1
# 11 13.367 -14.619 5
但是如何让 interaction
命令保留顺序,以便上面的第一个 Cluster_ID 为 1(最后一列的完整矢量为 1,1,1,1,2 ,2,2,3,3,4,5 而不是 2,2,2,2,3,3,4,4,1,5)?目前还不清楚新的因子顺序(转换为数字)是如何确定的。
我也一直在尝试使用 dplyr
中的 group_by
找到等效的方法,但无法弄清楚如何将小标题 table 输出为数据帧(较旧SO 上的解决方案似乎使用折旧的 dplyr 命令)。
谢谢!
我们可以使用match
transform(d, Cluster_ID = match(paste0(LAT, LONG), unique(paste0(LAT, LONG))))
或将'LAT'、'LONG'转换为序列,然后执行interaction
transform(d, Cluster_ID = as.integer(interaction(match(LAT,
unique(LAT)), match(LONG, unique(LONG)), drop=TRUE, lex.order = FALSE)))
data.table
选项使用 .GRP
> setDT(d)[, Cluster_ID := .GRP, .(LAT, LONG)][]
LAT LONG Cluster_ID
1: 13.533 -15.418 1
2: 13.533 -15.418 1
3: 13.533 -15.418 1
4: 13.533 -15.418 1
5: 13.533 -15.417 2
6: 13.533 -15.417 2
7: 13.533 -15.417 2
8: 13.534 -14.935 3
9: 13.534 -14.935 3
10: 13.534 -15.917 4
11: 13.367 -14.619 5
或rleid
(感谢@akrun的评论)
> setDT(d)[, Cluster_ID := rleid(LAT, LONG)][]
LAT LONG Cluster_ID
1: 13.533 -15.418 1
2: 13.533 -15.418 1
3: 13.533 -15.418 1
4: 13.533 -15.418 1
5: 13.533 -15.417 2
6: 13.533 -15.417 2
7: 13.533 -15.417 2
8: 13.534 -14.935 3
9: 13.534 -14.935 3
10: 13.534 -15.917 4
11: 13.367 -14.619 5
或使用 ave
+ cumsum
的基础 R 选项
transform(
d,
Cluster_ID = cumsum(
ave(1:nrow(d),
LAT,
LONG,
FUN = seq_along
) == 1
)
)
有人问过这个问题,但我正在寻找更完整的 answer/slightly 修改后的输出。
我有一个数据集,其中 Lat 和 Long 值位于不同的列中,我想为 Lat 和 Long 的每个唯一组合创建一个唯一 ID。
我将从较旧的 post 那里借用一个示例数据集来问同样的问题,但我需要一个稍微不同的解决方案 (Add ID column by group)。
d <- read.table(text='LAT LONG
13.5330 -15.4180
13.5330 -15.4180
13.5330 -15.4180
13.5330 -15.4180
13.5330 -15.4170
13.5330 -15.4170
13.5330 -15.4170
13.5340 -14.9350
13.5340 -14.9350
13.5340 -15.9170
13.3670 -14.6190', header=TRUE)
给出的解决方案是:
d <- transform(d, Cluster_ID = as.numeric(interaction(LAT, LONG, drop=TRUE)))
# LAT LONG Cluster_ID
# 1 13.533 -15.418 2
# 2 13.533 -15.418 2
# 3 13.533 -15.418 2
# 4 13.533 -15.418 2
# 5 13.533 -15.417 3
# 6 13.533 -15.417 3
# 7 13.533 -15.417 3
# 8 13.534 -14.935 4
# 9 13.534 -14.935 4
# 10 13.534 -15.917 1
# 11 13.367 -14.619 5
但是如何让 interaction
命令保留顺序,以便上面的第一个 Cluster_ID 为 1(最后一列的完整矢量为 1,1,1,1,2 ,2,2,3,3,4,5 而不是 2,2,2,2,3,3,4,4,1,5)?目前还不清楚新的因子顺序(转换为数字)是如何确定的。
我也一直在尝试使用 dplyr
中的 group_by
找到等效的方法,但无法弄清楚如何将小标题 table 输出为数据帧(较旧SO 上的解决方案似乎使用折旧的 dplyr 命令)。
谢谢!
我们可以使用match
transform(d, Cluster_ID = match(paste0(LAT, LONG), unique(paste0(LAT, LONG))))
或将'LAT'、'LONG'转换为序列,然后执行interaction
transform(d, Cluster_ID = as.integer(interaction(match(LAT,
unique(LAT)), match(LONG, unique(LONG)), drop=TRUE, lex.order = FALSE)))
data.table
选项使用 .GRP
> setDT(d)[, Cluster_ID := .GRP, .(LAT, LONG)][]
LAT LONG Cluster_ID
1: 13.533 -15.418 1
2: 13.533 -15.418 1
3: 13.533 -15.418 1
4: 13.533 -15.418 1
5: 13.533 -15.417 2
6: 13.533 -15.417 2
7: 13.533 -15.417 2
8: 13.534 -14.935 3
9: 13.534 -14.935 3
10: 13.534 -15.917 4
11: 13.367 -14.619 5
或rleid
(感谢@akrun的评论)
> setDT(d)[, Cluster_ID := rleid(LAT, LONG)][]
LAT LONG Cluster_ID
1: 13.533 -15.418 1
2: 13.533 -15.418 1
3: 13.533 -15.418 1
4: 13.533 -15.418 1
5: 13.533 -15.417 2
6: 13.533 -15.417 2
7: 13.533 -15.417 2
8: 13.534 -14.935 3
9: 13.534 -14.935 3
10: 13.534 -15.917 4
11: 13.367 -14.619 5
或使用 ave
+ cumsum
transform(
d,
Cluster_ID = cumsum(
ave(1:nrow(d),
LAT,
LONG,
FUN = seq_along
) == 1
)
)