在没有循环的情况下在 Dataframe 中子字符串、填充和粘贴列
Substring, Pad and Paste Columns in Dataframe without a Loop
我有这个数据框,它看起来像这样:
我需要从 at 列中取出第一个字符,an 中的整个值,然后在末尾放置一个计数器,随着 an 列中的重复而递增。该计数器的长度必须始终为三。最终结果是这样的:
所以这里没什么特别的,我可以用下面的代码做到这一点(准备留下深刻的印象):
library(stringr)
tk <- ""
for (i in 1:nrow(df)){
if (tk == df$an[i]){
counter <- counter + 1
} else {
tk <- df$an[i]
counter <- 1
}
df$ap[i] <- counter
}
df$ap <- paste0(substr(df$at, 1, 1), df$an, str_pad(df$ap, 3, pad="0"))
我对这次崩溃非常不满意。它似乎不是很 "R",我非常希望永远不要让它出现。我怎样才能使它更 "R"?
感谢您的建议。
这个有效:
library(stringr)
df = data.frame(at=c("NDA","ANDA","ANDA","NDA","ANDA"),an=c("023356","023357","023357","023357","023398"),stringsAsFactors = F)
df$ap = paste0(substr(df$at,1,1),
df$an,str_pad(ave(df$an, df$an, FUN = seq_along),width=3,pad="0"))
输出:
at an ap
1 NDA 023356 N023356001
2 ANDA 023357 A023357001
3 ANDA 023357 A023357002
4 NDA 023357 N023357003
5 ANDA 023398 A023398001
希望对您有所帮助!
library(stringr)
library(dplyr)
df1 <- df %>%
group_by(an) %>%
mutate(ap=paste0(substr(at, 1, 1), an, str_pad(row_number(), 3, pad="0")))
at an ap
1 NDA 023356 N023356001
2 ANDA 023357 A023357001
3 ANDA 023357 A023357002
4 NDA 023357 N023357003
5 ANDA 023398 A023398001
在 base R 中,您可以使用 sprintf
填充 0 并 ave 得到这样的计数:
df$ap <- paste0(substr(df$at, 1, 1), df$an,
sprintf("%03.0f", as.numeric(ave(df$an, df$an, FUN=seq_along))))
ave
执行组计算,seq_along
计算行数。
哪个returns
df
at an ap
1 NDA 023356 N023356001
2 ANDA 023357 A023357001
3 ANDA 023357 A023357002
4 NDA 023357 N023357003
5 ANDA 023398 A023398001
data.table 中的 rleid
和 rowid
函数在这里很有用:
# using df from @Florian's answer
library(data.table)
setDT(df)
df[, v := paste0(
substr(at, 1, 1),
an,
sprintf("%03.f", rowid(rleid(an)))
)]
# at an v
# 1: NDA 023356 N023356001
# 2: ANDA 023357 A023357001
# 3: ANDA 023357 A023357002
# 4: NDA 023357 N023357003
# 5: ANDA 023398 A023398001
工作原理:
来自 base 的 sprintf
有效地完成了 OP 中 stringr::str_pad
的工作。
rleid
将一系列重复值组合在一起。
rowid
在每组中制作一个计数器。
我有这个数据框,它看起来像这样:
我需要从 at 列中取出第一个字符,an 中的整个值,然后在末尾放置一个计数器,随着 an 列中的重复而递增。该计数器的长度必须始终为三。最终结果是这样的:
所以这里没什么特别的,我可以用下面的代码做到这一点(准备留下深刻的印象):
library(stringr)
tk <- ""
for (i in 1:nrow(df)){
if (tk == df$an[i]){
counter <- counter + 1
} else {
tk <- df$an[i]
counter <- 1
}
df$ap[i] <- counter
}
df$ap <- paste0(substr(df$at, 1, 1), df$an, str_pad(df$ap, 3, pad="0"))
我对这次崩溃非常不满意。它似乎不是很 "R",我非常希望永远不要让它出现。我怎样才能使它更 "R"?
感谢您的建议。
这个有效:
library(stringr)
df = data.frame(at=c("NDA","ANDA","ANDA","NDA","ANDA"),an=c("023356","023357","023357","023357","023398"),stringsAsFactors = F)
df$ap = paste0(substr(df$at,1,1),
df$an,str_pad(ave(df$an, df$an, FUN = seq_along),width=3,pad="0"))
输出:
at an ap
1 NDA 023356 N023356001
2 ANDA 023357 A023357001
3 ANDA 023357 A023357002
4 NDA 023357 N023357003
5 ANDA 023398 A023398001
希望对您有所帮助!
library(stringr)
library(dplyr)
df1 <- df %>%
group_by(an) %>%
mutate(ap=paste0(substr(at, 1, 1), an, str_pad(row_number(), 3, pad="0")))
at an ap
1 NDA 023356 N023356001
2 ANDA 023357 A023357001
3 ANDA 023357 A023357002
4 NDA 023357 N023357003
5 ANDA 023398 A023398001
在 base R 中,您可以使用 sprintf
填充 0 并 ave 得到这样的计数:
df$ap <- paste0(substr(df$at, 1, 1), df$an,
sprintf("%03.0f", as.numeric(ave(df$an, df$an, FUN=seq_along))))
ave
执行组计算,seq_along
计算行数。
哪个returns
df
at an ap
1 NDA 023356 N023356001
2 ANDA 023357 A023357001
3 ANDA 023357 A023357002
4 NDA 023357 N023357003
5 ANDA 023398 A023398001
data.table 中的 rleid
和 rowid
函数在这里很有用:
# using df from @Florian's answer
library(data.table)
setDT(df)
df[, v := paste0(
substr(at, 1, 1),
an,
sprintf("%03.f", rowid(rleid(an)))
)]
# at an v
# 1: NDA 023356 N023356001
# 2: ANDA 023357 A023357001
# 3: ANDA 023357 A023357002
# 4: NDA 023357 N023357003
# 5: ANDA 023398 A023398001
工作原理:
-
来自 base 的
sprintf
有效地完成了 OP 中stringr::str_pad
的工作。rleid
将一系列重复值组合在一起。rowid
在每组中制作一个计数器。