在 id 中,我的数据具有多个非唯一的 name 标签。我想创建第三列,以使非唯一名称在其末尾粘贴字母以创建唯一名称。
dat <- structure(list(id = c("172262", "172262", "172262", "172262",
"172504", "172504", "172504", "172507", "172507", "172507"),
name = c("Fam", "Fam", "Fam", "CM_fam", "CBT_Fam", "CBT_Fam",
"CBT_Fam", "TAU", "CBT_Educ", "CBT_MI")), class = c("tbl_df",
"tbl", "data.frame"), row.names = c(NA, -10L))
所需的输出是:
id name unique_name
172262 Fam Fam_a
172262 Fam Fam_b
172262 Fam Fam_c
172262 CM_fam CM_fam
172504 CBT_Fam CBT_Fam_a
172504 CBT_Fam CBT_Fam_b
172504 CBT_Fam CBT_Fam_c
172507 TAU TAU
172507 CBT_Educ CBT_Educ
172507 CBT_MI CBT_MI
答案 0 :(得分:3)
您可以将paste
或sprintf
与letters
一起使用...
dat %>% group_by(id, name) %>% mutate(uname =
if (n() > 1) sprintf("%s_%s", name, letters[row_number()])
else name
)
# A tibble: 10 x 3
# Groups: id, name [6]
id name uname
<chr> <chr> <chr>
1 172262 Fam Fam_a
2 172262 Fam Fam_b
3 172262 Fam Fam_c
4 172262 CM_fam CM_fam
5 172504 CBT_Fam CBT_Fam_a
6 172504 CBT_Fam CBT_Fam_b
7 172504 CBT_Fam CBT_Fam_c
8 172507 TAU TAU
9 172507 CBT_Educ CBT_Educ
10 172507 CBT_MI CBT_MI
对于tidyverse(dplyr所属的)中的其他字符串操作,可能会看到stringr和粘胶。
答案 1 :(得分:2)
您可以使用ave
(以R
为基础)
transform(dat, unique_name =
ave(name,name, FUN = function(x) {
if((l <- length(x)) == 1) x
else paste0(x,"_",letters[seq(l)])
}))
# id name unique_name
# 1 172262 Fam Fam_a
# 2 172262 Fam Fam_b
# 3 172262 Fam Fam_c
# 4 172262 CM_fam CM_fam
# 5 172504 CBT_Fam CBT_Fam_a
# 6 172504 CBT_Fam CBT_Fam_b
# 7 172504 CBT_Fam CBT_Fam_c
# 8 172507 TAU TAU
# 9 172507 CBT_Educ CBT_Educ
# 10 172507 CBT_MI CBT_MI
还有一个代码高尔夫,虽然不通用:
dat$unique_name <- chartr(
make.unique(dat$name,sep="_"),old="123456789",new="abcdefghi")
dat
# # A tibble: 10 x 3
# id name unique_name
# <chr> <chr> <chr>
# 1 172262 Fam Fam
# 2 172262 Fam Fam_a
# 3 172262 Fam Fam_b
# 4 172262 CM_fam CM_fam
# 5 172504 CBT_Fam CBT_Fam
# 6 172504 CBT_Fam CBT_Fam_a
# 7 172504 CBT_Fam CBT_Fam_b
# 8 172507 TAU TAU
# 9 172507 CBT_Educ CBT_Educ
# 10 172507 CBT_MI CBT_MI
答案 2 :(得分:1)
另一种 dat %>%
group_by(id, name) %>%
mutate(unique_name = if(n() > 1) paste(name, letters[1:length(name)], sep = "_") else name)
id name unique_name
<chr> <chr> <chr>
1 172262 Fam Fam_a
2 172262 Fam Fam_b
3 172262 Fam Fam_c
4 172262 CM_fam CM_fam
5 172504 CBT_Fam CBT_Fam_a
6 172504 CBT_Fam CBT_Fam_b
7 172504 CBT_Fam CBT_Fam_c
8 172507 TAU TAU
9 172507 CBT_Educ CBT_Educ
10 172507 CBT_MI CBT_MI
可能性是:
length()
首先,它按“ id”和“ name”分组。然后,如果每组的案例数大于1,则将“名称”中的值与“名称”长度的字母序列组合在一起,否则将分配“名称”中的值。
或者使用n()
,而不是dat %>%
group_by(id, name) %>%
mutate(unique_name = if(length(name) > 1) paste(name, letters[1:length(name)], sep = "_") else name)
:
seq_along()
或者使用n()
代替dat %>%
group_by(id, name) %>%
mutate(unique_name = if(any(seq_along(name) != 1)) paste(name, letters[1:length(name)], sep = "_") else name)
:
gl()
或者使用dat %>%
group_by(id, name) %>%
mutate(unique_name = if(n() > 1) paste(name, gl(length(name), 1, n(), letters), sep = "_") else name)
id name unique_name
<chr> <chr> <chr>
1 172262 Fam Fam_a
2 172262 Fam Fam_b
3 172262 Fam Fam_c
4 172262 CM_fam CM_fam
5 172504 CBT_Fam CBT_Fam_a
6 172504 CBT_Fam CBT_Fam_b
7 172504 CBT_Fam CBT_Fam_c
8 172507 TAU TAU
9 172507 CBT_Educ CBT_Educ
10 172507 CBT_MI CBT_MI
生成字母的方法稍有不同:
dat %>%
group_by(id, name) %>%
mutate(unique_name = if(length(name) > 1) paste(name, gl(length(name), 1, n(), letters), sep = "_") else name)
或者:
dat %>%
group_by(id, name) %>%
mutate(unique_name = if(any(seq_along(name) != 1)) paste(name, gl(length(name), 1, n(), letters), sep = "_") else name)
或者:
{
"sensor_data": [
{
"sensor_id": "302CEM/lion/light1",
"sensor_state": "on"
},
{
"sensor_id": "302CEM/lion/light2",
"sensor_state": "off"
}
]
}
def read_from_db():
with open('datajson.json') as f:
data = json.load(f)
for sensors in data['sensor_data']:
name = sensors['sensor_id']
read_from_db()
答案 3 :(得分:1)
只需在此处带来一些data.table风味:
library(data.table)
DT <- as.data.table(dat)
DT[, unique_name := if (.N > 1) paste(name, letters[1:.N], sep = "_")
else name,
by = .(id, name)]
尽管,正如其他人指出的那样,如果您有26个以上重复的名称,您可能希望将letters[1:.N]
替换为1:.N
。
答案 4 :(得分:1)
可以从这里选择很多选项,但是如果您正在寻找一个相当简单的管道,并且可以使用格式有所不同的输出,则可以使用基数R中的make.unique
:
library(dplyr)
dat %>%
group_by(id, name) %>%
mutate(unique_name = make.unique(name))
哪种产量:
id name unique_name
<chr> <chr> <chr>
1 172262 Fam Fam
2 172262 Fam Fam.1
3 172262 Fam Fam.2
4 172262 CM_fam CM_fam
5 172504 CBT_Fam CBT_Fam
6 172504 CBT_Fam CBT_Fam.1
7 172504 CBT_Fam CBT_Fam.2
8 172507 TAU TAU
9 172507 CBT_Educ CBT_Educ
10 172507 CBT_MI CBT_MI