我进行了一些搜索,但找不到最合适的关键词来表达我的问题,所以我想我会在这里提问。
我正在处理R中的一个数据帧,该数据帧具有两个表示数据点身份的变量。在下面的示例中,A和1代表同一个人,B和2相同,C和3也相同,但是它们被混合在原始数据中。
ID1 ID2 Value
A 1 0.5
B 2 0.8
C C 0.7
A A 0.6
B 2 0.3
3 C 0.4
2 2 0.3
1 A 0.4
3 3 0.6
我想要实现的是通过仅使用一个标识符来统一身份,因此可以是:
ID1 ID2 Value ID
A 1 0.5 A
B 2 0.8 B
C C 0.7 C
A A 0.6 A
B 2 0.3 B
3 C 0.4 C
2 2 0.3 B
1 A 0.4 A
3 3 0.6 C
或:
ID1 ID2 Value ID
A 1 0.5 1
B 2 0.8 2
C C 0.7 3
A A 0.6 1
B 2 0.3 2
3 C 0.4 3
2 2 0.3 2
1 A 0.4 1
3 3 0.6 3
我可能可以通过使用ifelse
函数来实现它,但这意味着我必须为每个条件编写两个ifelse
语句,而且看起来效率不高,所以我想知道是否有更好的方法可以做吧。这是示例数据集。
df=data.frame(ID1=c("A","B","C","A","B","3","2","1","3"),
ID2=c("1","2","C","A","2","C","2","A","3"),
Value=c(0.5,0.8,0.7,0.6,0.3,0.4,0.3,0.4,0.6))
非常感谢您的帮助!
编辑:
为澄清起见,我在真实数据中拥有的两个标识符是更长的文本字符串,而不仅仅是ABC和123。抱歉,我并不清楚。
答案 0 :(得分:2)
一种选择是检测仅是数字的元素,转换为整数,然后在LETTERS
中获得相应的case_when
library(dplyr)
library(stringr)
df %>%
mutate(ID = case_when(str_detect(ID1, '\\d+')~
LETTERS[as.integer(ID1)], TRUE ~ ID1))
# ID1 ID2 Value ID
#1 A 1 0.5 A
#2 B 2 0.8 B
#3 C C 0.7 C
#4 A A 0.6 A
#5 B 2 0.3 B
#6 3 C 0.4 C
#7 2 2 0.3 B
#8 1 A 0.4 A
#9 3 3 0.6 C
或更紧凑
df %>%
mutate(ID = coalesce(LETTERS[as.integer(ID1)], ID1))
如果我们有不同的值集,则创建一个键/值数据集并进行联接
keyval <- data.frame(ID1 = c('1', '2', '3'), ID = c('A', 'B', 'C'))
left_join(df, keyval) %>% mutate(ID = coalesce(ID, ID1))
答案 1 :(得分:2)
使用replace
within(
df,
ID <- replace(
ID1,
!ID1 %in% LETTERS,
LETTERS[as.numeric(ID1[!ID1 %in% LETTERS])]
)
)
或ifelse
within(
df,
ID <- suppressWarnings(ifelse(ID1 %in% LETTERS,
ID1,
LETTERS[as.integer(ID1)]
))
)
给出
ID1 ID2 Value ID
1 A 1 0.5 A
2 B 2 0.8 B
3 C C 0.7 C
4 A A 0.6 A
5 B 2 0.3 B
6 3 C 0.4 C
7 2 2 0.3 B
8 1 A 0.4 A
9 3 3 0.6 C