基于R中的3个公共变量创建ID变量

时间:2013-01-24 18:53:06

标签: r variables sorting dataframe

我有以下数据框(下面),它是我的完整数据集的子集。我需要为具有相同LAT / LONG和着陆日期的每个条目定义相同的ID。我之前订购的LANDEDDATE从最早到最晚。

 > dput(df2)
structure(list(LATITUDE = c(43.35, 43.35, 43.35, 43.35, 43.35, 
43.35, 43.35, 43.35, 43.5166, 43.5166, 43.5166, 43.5166, 43.5166, 
43.5166, 43.5166, 42.9833, 42.9833, 42.9833, 42.9666, 42.9666
), LONGITUDE = c(-60.6163, -60.6165, -60.7167, -60.7166, -60.7163, 
-60.716, -60.7169, -60.7166, -59.9169, -59.9168, -59.9169, -59.9166, 
-59.9166, -59.916, -59.916, -61.8333, -61.8333, -61.8333, -61.9161, 
-61.9161), LANDEDDATE = structure(c(11171, 11171, 11183, 11183, 
11183, 11183, 11183, 11183, 11192, 11192, 11192, 11192, 11192, 
11192, 11192, 11210, 11210, 11210, 11210, 11210), class = "Date"), 
    sppCODE = c(251L, 251L, 251L, 251L, 251L, 251L, 251L, 251L, 
    251L, 251L, 251L, 251L, 251L, 256L, 251L, 256L, 252L, 251L, 
    251L, 252L), LIVEW = c(0.337, 0.471, 0.238, 0.772, 0.178, 
    0.416, 0.535, 0.356, 0.442, 0.663, 0.442, 0.497, 0.276, 0.032, 
    0.828, 0.035, 0.011, 1.224, 1.025, 0.072), SPECIES = structure(c(7L, 
    7L, 7L, 7L, 7L, 7L, 7L, 7L, 7L, 7L, 7L, 7L, 7L, 7L, 7L, 7L, 
    7L, 7L, 7L, 7L), .Label = c("Albacore Tuna", "Bigeye Tuna", 
    "Bluefin Tuna", "Mako", "Porbeagle", "Shark, UNSP", "Swordfish", 
    "Tuna, UNSP", "White Marlin", "Yellowfin Tuna"), class = "factor")), .Names = c("LATITUDE", 
"LONGITUDE", "LANDEDDATE", "sppCODE", "LIVEW", "SPECIES"), row.names = c(19L, 
20L, 13L, 14L, 15L, 16L, 17L, 18L, 6L, 7L, 8L, 9L, 10L, 11L, 
12L, 1L, 2L, 3L, 4L, 5L), class = "data.frame")

这是我到目前为止所做的,但我无法弄清楚其余部分。

    df2$setID<-"NA" #I created an empty setID.
    > head(df2)
   LATITUDE LONGITUDE LANDEDDATE sppCODE LIVEW   SPECIES setID
19    43.35  -60.6163 2000-08-02     251 0.337 Swordfish    NA
20    43.35  -60.6165 2000-08-02     251 0.471 Swordfish    NA
13    43.35  -60.7167 2000-08-14     251 0.238 Swordfish    NA
14    43.35  -60.7166 2000-08-14     251 0.772 Swordfish    NA
15    43.35  -60.7163 2000-08-14     251 0.178 Swordfish    NA
16    43.35  -60.7160 2000-08-14     251 0.416 Swordfish    NA
unique<-df2[which(!duplicated(df2[,1:3])),] #This is each entry that are NOT duplicate
unique2$setID<-1:13 # Ranked from 1:13
> head(unique) #looks like that
   LATITUDE LONGITUDE LANDEDDATE sppCODE LIVEW   SPECIES setID
19    43.35  -60.6163 2000-08-02     251 0.337 Swordfish     1
20    43.35  -60.6165 2000-08-02     251 0.471 Swordfish     2
13    43.35  -60.7167 2000-08-14     251 0.238 Swordfish     3
14    43.35  -60.7166 2000-08-14     251 0.772 Swordfish     4
15    43.35  -60.7163 2000-08-14     251 0.178 Swordfish     5
16    43.35  -60.7160 2000-08-14     251 0.416 Swordfish     6
rep<-df2[which(duplicated(df2[,1:3])),] #This is all my replicates

我需要将我的唯一数据帧的setID分配给rep数据帧中的相应集合(具有相同LAT / LONG和LANDEDDATE的复制)。任何建议将不胜感激!

3 个答案:

答案 0 :(得分:7)

您可以使用interaction

within(df2, {id = interaction(LATITUDE,LONGITUDE,LANDEDDATE)})
  LATITUDE LONGITUDE LANDEDDATE sppCODE LIVEW   SPECIES                        id
19    43.35  -60.6163 2000-08-02     251 0.337 Swordfish 43.35.-60.6163.2000-08-02
20    43.35  -60.6165 2000-08-02     251 0.471 Swordfish 43.35.-60.6165.2000-08-02
13    43.35  -60.7167 2000-08-14     251 0.238 Swordfish 43.35.-60.7167.2000-08-14
14    43.35  -60.7166 2000-08-14     251 0.772 Swordfish 43.35.-60.7166.2000-08-14
15    43.35  -60.7163 2000-08-14     251 0.178 Swordfish 43.35.-60.7163.2000-08-14
.......

编辑添加drop = TRUE选项(效率更高)(@ Matthew评论),并更改分隔符(更智能)

res1 <- within(df2, {id = interaction(
                           sprintf("%5.2f", LATITUDE),
                           sprintf("%5.2f", LONGITUDE),
                           LANDEDDATE,drop=TRUE,sep=':')})

res1
   LATITUDE LONGITUDE LANDEDDATE sppCODE LIVEW   SPECIES                      id
19  43.3500  -60.6163 2000-08-02     251 0.337 Swordfish 43.35:-60.62:2000-08-02
20  43.3500  -60.6165 2000-08-02     251 0.471 Swordfish 43.35:-60.62:2000-08-02
13  43.3500  -60.7167 2000-08-14     251 0.238 Swordfish 43.35:-60.72:2000-08-14
14  43.3500  -60.7166 2000-08-14     251 0.772 Swordfish 43.35:-60.72:2000-08-14
15  43.3500  -60.7163 2000-08-14     251 0.178 Swordfish 43.35:-60.72:2000-08-14
16  43.3500  -60.7160 2000-08-14     251 0.416 Swordfish 43.35:-60.72:2000-08-14
17  43.3500  -60.7169 2000-08-14     251 0.535 Swordfish 43.35:-60.72:2000-08-14
18  43.3500  -60.7166 2000-08-14     251 0.356 Swordfish 43.35:-60.72:2000-08-14
6   43.5166  -59.9169 2000-08-23     251 0.442 Swordfish 43.52:-59.92:2000-08-23
7   43.5166  -59.9168 2000-08-23     251 0.663 Swordfish 43.52:-59.92:2000-08-23

答案 1 :(得分:6)

这听起来像很多争吵!

为什么不使用paste

之类的东西创建“密钥”
paste(df2$LONGITUDE, df2$LATITUDE, df2$LANDEDDATE)

然后您可以使用factor并将其强制转换回其基础整数:

df2$setID <- as.integer(factor(paste(df2$LONGITUDE, df2$LATITUDE, df2$LANDEDDATE)))

如果您的数据很大(或者即使不是!),您也可以使用data.table执行此操作。

library(data.table)
df2 <- data.table(df2, key=c('LATITUDE', 'LONGITUDE', 'LANDEDDATE'))

df2[, setID := (.GRP), by=c('LATITUDE', 'LONGITUDE', 'LANDEDDATE')]

答案 2 :(得分:2)

id中的plyr功能旨在尽可能高效地执行此操作:

library(plyr)
id(df2[c("LATITUDE", "LONGITUDE", "LANDEDDATE")])
id(df2[c("LATITUDE", "LONGITUDE", "LANDEDDATE")], drop = TRUE)

如果您按照该变量对数据框进行排序,则它具有该属性,如果您按纬度,日志和日期对其进行排序,则该变量将按相同顺序排列。

这是一个小基准,并不是说除非您的实际数据远大于此值,否则它可能会有很大差异:

library(microbenchmark)
df3 <- df2[c("LATITUDE", "LONGITUDE", "LANDEDDATE")]

microbenchmark(
  id(df3),
  id(df3, drop = TRUE),
  interaction(df3),
  interaction(df3, drop = TRUE))
# Unit: microseconds
#                          expr  min   lq median   uq  max neval
#                       id(df3)  366  386    397  412  575   100
#          id(df3, drop = TRUE)  421  443    460  476 1823   100
#              interaction(df3)  622  657    672  698  987   100
# interaction(df3, drop = TRUE) 1006 1053   1079 1108 2210   100