我对R很陌生,我正在努力解决这个看起来很简单的问题,但我不知道该怎么做。我正在尝试比较两个数据帧,打印出其中一个而不是另一个中的行,还打印另一个列表/数据帧,其中只有一个单元格更新。
df1
firstname lastname email
Grace Holly hollyoaks@yahoo.com
Trish Edison edisontrish@gmail.com
df2
firstname lastname email
Grace Holly rickyoaks@yahoo.com
Frederick Sam sammic@gmail.com
我想做的第一件事是获取df2中而不是df1中的行,我就是这样做的:
require(sqldf)
df2NotIndf1 <- sqldf('SELECT * FROM df2 EXCEPT SELECT * FROM df1')
这给了我输出:
`firstname lastname email`
`Frederick Sam sammic@gmail.com`
现在,我想要的是一种方法,通过注意名字和姓氏相同,但电子邮件不同,将第一行作为自己的输出。
所以,我想要一种打印出来的方法:
firstname lastname email
Grace Holly rickyoaks@yahoo.com
我看了compare((函数、merge和其他函数,但它们似乎是在进行比较,以发现不同的行,而不是不同的单元格。
首先,我创建数据帧。
# Create data frames
df1 <- read.table(text = "firstname lastname email
Grace Holly hollyoaks@yahoo.com
Trish Edison edisontrish@gmail.com", ,
header = TRUE, stringsAsFactors = FALSE)
df2 <- read.table(text = "firstname lastname email
Grace Holly rickyoaks@yahoo.com
Frederick Sam sammic@gmail.com",
header = TRUE, stringsAsFactors = FALSE)
接下来,我加载dplyr
。
# Load libraries
library(dplyr)
在这里,我执行反联接以查找df2
中不在df1
中的行。
# Perform antijoin
df3 <- df2 %>% anti_join(df1, by = c("firstname", "lastname"))
# firstname lastname email
# 1 Frederick Sam sammic@gmail.com
然后,我将原始的两个数据帧绑定在一起,删除之前标识为仅出现在df2
中的行,然后使用除一列之外的所有列检查重复项。如果除一列外,所有列中都有重复项,则保留这些行。
# Bind two data frames together
# Remove those only appearing in df2
# Filter to those with duplicates in all but one column
df1 %>%
bind_rows(df2) %>%
anti_join(df3) %>%
filter((duplicated(firstname, lastname) + duplicated(email, lastname) + duplicated(firstname, email)) == ncol(df1) - 1)
# firstname lastname email
# 1 Grace Holly rickyoaks@yahoo.com
我目前正在考虑一种更简洁的方式来编写filter
行,它可以概括为任意数量的列。
1(如果您正在寻找一种方法来列出那些名字和姓氏都在df1和df2中但电子邮件不同的人,那么:
sqldf("select df1.*, df2.email email2
from df1
join df2 on df1.firstname = df2.firstname and
df1.lastname = df2.lastname and
df1.email <> df2.email")
下面给出了df1记录和与df2不同的电子邮件。
firstname lastname email email2
1 Grace Holly hollyoaks@yahoo.com rickyoaks@yahoo.com
2(或基本解决方案为:
subset(merge(df1, df2, by = 1:2), email.x != email.y)
备注
以可复制形式使用的输入是:
Lines1 <- "firstname lastname email
Grace Holly hollyoaks@yahoo.com
Trish Edison edisontrish@gmail.com"
Lines2 <- "firstname lastname email
Grace Holly rickyoaks@yahoo.com
Frederick Sam sammic@gmail.com"
df1 <- read.table(text = Lines1, header = TRUE, as.is = TRUE, strip.white = TRUE)
df2 <- read.table(text = Lines2, header = TRUE, as.is = TRUE, strip.white = TRUE)