我正在使用一个仅包含两列的数据框,其中一列对应于虚拟机生成的唯一 ID,第二列包含一个名称。但是,此特定列也可能包含字符串“ERROR”。
目标是创建一个脚本,使我们能够在每次找到字符串“ERROR”时进行识别,并捕获其周围的姓氏和后续名称以及分配给字符串“ERROR”的唯一 ID。为了说明这一点,让我们看一下下面的例子:
如果我有这些数据:
身份证 | 姓名 |
---|---|
1 | 詹姆斯 |
3 | 错误 |
6 | 喀拉斯 |
88 | 凯莉 |
53 | 迈克尔 |
55 | 错误 |
7 | 辛迪 |
834 | 喀拉斯 |
然后我们想得出以下列表:
身份证 | 姓名 |
---|---|
3 | 詹姆斯·凯拉斯 |
55 | 迈克尔-辛迪 |
这是因为找到的第一个字符串“ERROR”的 ID 为 3,位于 James(错误之前)和 Keras(错误之后)之间,下一个“ERROR”的 ID 为 55,位于 Micheal 和 Cindy 之间什么如果“ERROR”是列表的顶部或底部,那么我们应该只包含我们发现的任何名称,可以说“NA-NAME”是在顶部找到的错误...
但这就是棘手的地方;如果我们遇到一个包含连续字符串“ERROR”的序列,我们应该始终使用按降序排列的最后一个字符串作为“指南”:
如果我有这个数据集
身份证 | 姓名 |
---|---|
1 | 詹姆斯 |
3 | 错误 |
6 | 错误 |
88 | 错误 |
53 | 裘德 |
55 | 错误 |
7 | 辛迪 |
834 | 喀拉斯 |
那么我们就会想要
身份证 | 姓名 |
---|---|
88 | 詹姆斯-裘德 |
55 | 裘德-辛迪 |
这是因为字符串 ERROR 连续重复了 3 次,但最后一次在 ID 88 处,这意味着我们将以此为参考并记录其前后的名称。另一种看待这一问题的方法是将字符串“ERROR”视为一个块,因此我们将记录每个字符串“ERROR”块之前和之后的名称。
我们可以创建一个函数来执行此操作
f1 <- function(dat) {
subdat1 <- subset(dat, !duplicated(with(rle(NAMES == "ERROR"),
rep(seq_along(values), lengths)), fromLast = TRUE))
subdat2 <- subset(dat, !duplicated(with(rle(NAMES == "ERROR"),
rep(seq_along(values), lengths))))
ind <- which(subdat1$NAMES == "ERROR")
do.call(rbind, lapply(ind[c(TRUE, diff(ind) > 1)], function(i)
data.frame(ID = subdat1$ID[i],NAMES = paste(subdat1$NAMES[i-1],
subdat2$NAMES[i+1], sep="-"))))
}
-测试
> f1(df1)
ID NAMES
1 3 James-Keras
2 55 Micheal-Cindy
> f1(df2)
ID NAMES
1 88 James-Jude
2 55 Jude-Cindy
df1 <- structure(list(ID = c(1L, 3L, 6L, 88L, 53L, 55L, 7L, 834L), NAMES = c("James",
"ERROR", "Keras", "Kelly", "Micheal", "ERROR", "Cindy", "Keras"
)), class = "data.frame", row.names = c(NA, -8L))
df2 <- structure(list(ID = c(1L, 3L, 6L, 88L, 53L, 55L, 7L, 834L), NAMES = c("James",
"ERROR", "ERROR", "ERROR", "Jude", "ERROR", "Cindy", "Keras")),
class = "data.frame", row.names = c(NA,
-8L))