如何识别R中镜像的重复行
在下面的SO帖子中,我询问了如何消除部分重复的行。我的问题是: 我想识别数据帧中行的“部分”匹配。具体地说,如果基于列子集之间的匹配,数据帧中的某个特定行在数据帧的其他位置具有重复行,我希望创建一个值为1的新列。更复杂的是,数据框中的一列是数字,如果绝对值匹配,我希望匹配。 问题是,我需要确保当一行被标识为部分重复时,仅当匹配的一部分列是镜像相反的值,而不仅仅是绝对值上的匹配时,才会如此。为了让事情更清楚,以下是前一篇文章中的样本数据:如何识别R中镜像的重复行,r,R,在下面的SO帖子中,我询问了如何消除部分重复的行。我的问题是: 我想识别数据帧中行的“部分”匹配。具体地说,如果基于列子集之间的匹配,数据帧中的某个特定行在数据帧的其他位置具有重复行,我希望创建一个值为1的新列。更复杂的是,数据框中的一列是数字,如果绝对值匹配,我希望匹配。 问题是,我需要确保当一行被标识为部分重复时,仅当匹配的一部分列是镜像相反的值,而不仅仅是绝对值上的匹配时,才会如此。为了让事情更清楚,以下是前一篇文章中的样本数据: name<-c("Richard Nixon", "
name<-c("Richard Nixon", "Bill Clinton", "George Bush", "Richard Nixon")
state<-c("California", "Indiana", "Florida", "California")
num<-c("-258", "123", "42", "258")
date<-c("day 2", "day 15", "day 3","day 45")
(df<-as.data.frame(cbind(name,state,num, date)))
name state num date
1 Richard Nixon California -258 day 2
2 Bill Clinton Indiana 123 day 15
3 George Bush Florida 42 day 3
4 Richard Nixon California 258 day 45
请注意,第1行和第4行在newcol
下标记为TRUE
,这很好。这是新的样本数据,增加了复杂性问题:
name<-c("Richard Nixon", "Bill Clinton", "George Bush", "Richard Nixon", "Bill
Clinton")
state<-c("California", "Indiana", "Florida", "California", "Indiana")
num<-c("-258", "123", "42", "258", "123")
date<-c("day 2", "day 15", "day 3","day 45", "day 100")
(df<-as.data.frame(cbind(name,state,num, date)))
name state num date
1 Richard Nixon California -258 day 2
2 Bill Clinton Indiana 123 day 15
3 George Bush Florida 42 day 3
4 Richard Nixon California 258 day 45
5 Bill Clinton Indiana 123 day 100
前一篇SO帖子提供的解决方案将
TRUE
应用于第2行和第5行,而我只想将其应用于第1行和第4行。一个选项是首先将“num”转换为numeric
类型,创建另一列,其中包含abs
绝对值('num1'),按“name”、“state”、“num1”分组,mutate
通过检查行数等于2(n()==2
)和'num'的不同符号数大于1来创建布尔列
library(tidyverse)
df %>%
mutate(num = as.numeric(num), num1 = abs(num)) %>%
group_by(name, state, num1) %>%
mutate(newcol = n() == 2 & n_distinct(sign(num)) > 1) %>%
ungroup %>%
select(-num1)
# A tibble: 5 x 5
# name state num date newcol
# <chr> <chr> <dbl> <chr> <lgl>
#1 Richard Nixon California -258 day 2 TRUE
#2 Bill Clinton Indiana 123 day 15 FALSE
#3 George Bush Florida 42 day 3 FALSE
#4 Richard Nixon California 258 day 45 TRUE
#5 Bill Clinton Indiana 123 day 100 FALSE
在base R中,您可以使用与“部分”重复项上的链接问题相同的duplicated
测试,但随后排除相同的值
df$numnum = as.numeric(as.character(df$num))
df$absnum = abs(df$numnum)
df$newcol = (duplicated(df[,c('name','state', 'absnum')]) |
duplicated(df[,c('name','state', 'absnum')], fromLast = T)) &
!(duplicated(df$numnum) | duplicated(df$numnum, fromLast = T))
# name state num date numnum absnum newcol
# 1 Richard Nixon California -258 day 2 -258 258 TRUE
# 2 Bill Clinton Indiana 123 day 15 123 123 FALSE
# 3 George Bush Florida 42 day 3 42 42 FALSE
# 4 Richard Nixon California 258 day 45 258 258 TRUE
# 5 Bill Clinton Indiana 123 day 100 123 123 FALSE
您是否总是每个姓名和州最多只有两个条目?在有3+的情况下,您会怎么做?你会比较条目1和2,然后是2和3,然后是1和3吗?@Chase我提出了一个新的SO问题,试图解决你提到的这个问题:对不起,没关系。谢谢你的详细解释。@CyrusMohammadian。我根据您对的评论更改了n()==2
@Chase@In回想起来,我需要某种类型的顺序过程来识别沿num
变量彼此相加反转的匹配行。“为此,我开了一家新公司,我感谢所有的帮助,”CyrusMohammadian说。谢谢你告诉我最新情况。我在链接中发布了一个解决方案。希望能有帮助
library(tidyverse)
df %>%
mutate(num = as.numeric(num), num1 = abs(num)) %>%
group_by(name, state, num1) %>%
mutate(newcol = n() == 2 & n_distinct(sign(num)) > 1) %>%
ungroup %>%
select(-num1)
# A tibble: 5 x 5
# name state num date newcol
# <chr> <chr> <dbl> <chr> <lgl>
#1 Richard Nixon California -258 day 2 TRUE
#2 Bill Clinton Indiana 123 day 15 FALSE
#3 George Bush Florida 42 day 3 FALSE
#4 Richard Nixon California 258 day 45 TRUE
#5 Bill Clinton Indiana 123 day 100 FALSE
df <- data.frame(name, state, num, date, stringsAsFactors = FALSE)
df$numnum = as.numeric(as.character(df$num))
df$absnum = abs(df$numnum)
df$newcol = (duplicated(df[,c('name','state', 'absnum')]) |
duplicated(df[,c('name','state', 'absnum')], fromLast = T)) &
!(duplicated(df$numnum) | duplicated(df$numnum, fromLast = T))
# name state num date numnum absnum newcol
# 1 Richard Nixon California -258 day 2 -258 258 TRUE
# 2 Bill Clinton Indiana 123 day 15 123 123 FALSE
# 3 George Bush Florida 42 day 3 42 42 FALSE
# 4 Richard Nixon California 258 day 45 258 258 TRUE
# 5 Bill Clinton Indiana 123 day 100 123 123 FALSE