按元素比较两列
Compare two columns element-wise
我有一个大数据集 df
(354903 行),其中有两列名为 df$ColumnName
和 df$ColumnName.1
head(df)
CompleteName CompleteName.1
1 Lefebvre Arnaud Lefebvre Schuhl Anne
1.1 Lefebvre Arnaud Abe Lyu
1.2 Lefebvre Arnaud Abe Lyu
1.3 Lefebvre Arnaud Louvet Nicolas
1.4 Lefebvre Arnaud Muller Jean Michel
1.5 Lefebvre Arnaud De Dinechin Florent
我正在尝试创建标签以查看名称是否相同。
当我尝试一个小子集时它起作用 [如果它们相同则为 1,如果不同则为 0]:
> match(df$CompleteName[1], df$CompleteName.1[1], nomatch = 0)
[1] 0
> match(df$CompleteName[1:10], df$CompleteName.1[1:10], nomatch = 0)
[1] 0 0 0 0 0 0 0 0 0 0
但是一旦我抛出完整的列,它就会给我完全不同的值,这对我来说似乎是胡说八道:
> match(df$CompleteName, df$CompleteName.1, nomatch = 0)
[1] 101 101 101 101 101 101 101 101 101 101 101 101 101 101 101 101 101 101 101 101 101 101
[23] 101 101 101 101 101 101 101 101 101 101 101 101 101 101 101 101 101 101 101 101 101 101
[45] 101 101 101 101 101 101 101 101 101 101 101 101 101 101 101 101 101 101 101 101 101 101
我应该使用 sapply
吗?我没有弄清楚,我试过这个错误:
sapply(df, function(x) match(x$CompleteName, x$CompleteName.1, nomatch = 0))
请帮忙!!!
来自 match 的手册页,
‘match’ returns a vector of the positions of (first) matches of
its first argument in its second.
所以你的数据似乎表明 "Lefebvre Arnaud" 的第一个匹配项(第一个参数中的第一个位置)在第 101 行。我相信你打算做的是一个简单的比较,所以这是只是相等运算符 ==
.
一些示例数据:
> a <- rep ("Lefebvre Arnaud", 6)
> b <- c("Abe Lyu", "Abe Lyu", "Lefebvre Arnaud", rep("De Dinechin Florent", 3))
> x <- data.frame(a,b, stringsAsFactors=F)
> x
a b
1 Lefebvre Arnaud Abe Lyu
2 Lefebvre Arnaud Abe Lyu
3 Lefebvre Arnaud Lefebvre Arnaud
4 Lefebvre Arnaud De Dinechin Florent
5 Lefebvre Arnaud De Dinechin Florent
6 Lefebvre Arnaud De Dinechin Florent
> x$a == x$b
[1] FALSE FALSE TRUE FALSE FALSE FALSE
编辑: 此外,您需要确保您是在同类比较,因此请仔细检查列的数据类型。使用 str(df)
查看列是字符串还是因子。您可以使用 "stringsAsFactors = FALSE" 构造矩阵,也可以将因子转换为字符。有几种方法可以做到这一点,请在此处查看:Convert data.frame columns from factors to characters
正如其他人所指出的,match
不在这里。你想要的是平等,你可以通过 ==
测试得到,这会给你 TRUE/FALSE
。然后使用 as.numeric
将为您提供所需的 1/0
或使用 which
将为您提供索引。
但是您可能仍然对因素有疑问!
# making up some similar data( adapted from earlier answer)
a <- rep ("Lefebvre Arnaud", 6)
b <- c("Abe Lyu", "Abe Lyu", "Lefebvre Arnaud", rep("De Dinechin Florent", 3))
df <- data.frame(CompleteName = a, CompleteName.1 = b)
which(df$CompleteName == df$CompleteName1)
#integer(0)
#Warning message:
#In is.na(e2) : is.na() applied to non-(list or vector) of type 'NULL'
str(df)
# 'data.frame': 6 obs. of 2 variables:
# $ CompleteName : Factor w/ 1 level "Lefebvre Arnaud": 1 1 1 1 1 1
# $ CompleteName.1: Factor w/ 3 levels "Abe Lyu","De Dinechin Florent",..: 1 1 3 2 2 2
stringsAsFactors
上面的 data.frame 不是用 stringsAsFactors=FALSE
构造的,因此导致了错误。不幸的是,开箱即用的 R
会将字符串强制转换为加载 csv
或创建 data.frame
的因素。这可以在创建 data.frame 时通过显式指定 stringsAsFactors=FALSE
来解决
df <- data.frame(CompleteName = a, CompleteName.1 = b, stringsAsFactors = FALSE)
df[which(df$CompleteName == df$CompleteName.1), ]
## CompleteName CompleteName.1
## 3 Lefebvre Arnaud Lefebvre Arnaud
为避免将来出现此问题,请在 R 会话开始时 运行 options(stringsAsFactors = FALSE)
(或将其放在 .R
脚本的顶部)。更多讨论在这里:
- disable stringsAsFactors
这是一个使用 data.table
的解决方案,与 data.frame
解决方案的性能比较基于与您的情况相同的记录数。
col1 = sample(x = letters, size = 354903, replace = TRUE)
col2 = sample(x = letters, size = 354903, replace = TRUE)
library(data.table)
dt = data.table(col1 = col1, col2 = col2)
df = data.frame(col1 = col1, col2 = col2)
# comparing the 2 columns
system.time(dt$col1==dt$col2)
system.time(df$col1==df$col2)
# storing the comparison in the table/frame itself
system.time(dt[, col3:= (col1==col2)])
system.time({df$col3 = (df$col1 == df$col2)})
data.table
方法在我的机器上提供了显着的加速:从 0.020 秒到 0.008 秒。
亲自尝试看看。我知道这对于如此少的行数来说并不是很重要,但是将其乘以 1000,您会看到很大的不同!
我有一个大数据集 df
(354903 行),其中有两列名为 df$ColumnName
和 df$ColumnName.1
head(df)
CompleteName CompleteName.1
1 Lefebvre Arnaud Lefebvre Schuhl Anne
1.1 Lefebvre Arnaud Abe Lyu
1.2 Lefebvre Arnaud Abe Lyu
1.3 Lefebvre Arnaud Louvet Nicolas
1.4 Lefebvre Arnaud Muller Jean Michel
1.5 Lefebvre Arnaud De Dinechin Florent
我正在尝试创建标签以查看名称是否相同。 当我尝试一个小子集时它起作用 [如果它们相同则为 1,如果不同则为 0]:
> match(df$CompleteName[1], df$CompleteName.1[1], nomatch = 0)
[1] 0
> match(df$CompleteName[1:10], df$CompleteName.1[1:10], nomatch = 0)
[1] 0 0 0 0 0 0 0 0 0 0
但是一旦我抛出完整的列,它就会给我完全不同的值,这对我来说似乎是胡说八道:
> match(df$CompleteName, df$CompleteName.1, nomatch = 0)
[1] 101 101 101 101 101 101 101 101 101 101 101 101 101 101 101 101 101 101 101 101 101 101
[23] 101 101 101 101 101 101 101 101 101 101 101 101 101 101 101 101 101 101 101 101 101 101
[45] 101 101 101 101 101 101 101 101 101 101 101 101 101 101 101 101 101 101 101 101 101 101
我应该使用 sapply
吗?我没有弄清楚,我试过这个错误:
sapply(df, function(x) match(x$CompleteName, x$CompleteName.1, nomatch = 0))
请帮忙!!!
来自 match 的手册页,
‘match’ returns a vector of the positions of (first) matches of its first argument in its second.
所以你的数据似乎表明 "Lefebvre Arnaud" 的第一个匹配项(第一个参数中的第一个位置)在第 101 行。我相信你打算做的是一个简单的比较,所以这是只是相等运算符 ==
.
一些示例数据:
> a <- rep ("Lefebvre Arnaud", 6)
> b <- c("Abe Lyu", "Abe Lyu", "Lefebvre Arnaud", rep("De Dinechin Florent", 3))
> x <- data.frame(a,b, stringsAsFactors=F)
> x
a b
1 Lefebvre Arnaud Abe Lyu
2 Lefebvre Arnaud Abe Lyu
3 Lefebvre Arnaud Lefebvre Arnaud
4 Lefebvre Arnaud De Dinechin Florent
5 Lefebvre Arnaud De Dinechin Florent
6 Lefebvre Arnaud De Dinechin Florent
> x$a == x$b
[1] FALSE FALSE TRUE FALSE FALSE FALSE
编辑: 此外,您需要确保您是在同类比较,因此请仔细检查列的数据类型。使用 str(df)
查看列是字符串还是因子。您可以使用 "stringsAsFactors = FALSE" 构造矩阵,也可以将因子转换为字符。有几种方法可以做到这一点,请在此处查看:Convert data.frame columns from factors to characters
正如其他人所指出的,match
不在这里。你想要的是平等,你可以通过 ==
测试得到,这会给你 TRUE/FALSE
。然后使用 as.numeric
将为您提供所需的 1/0
或使用 which
将为您提供索引。
但是您可能仍然对因素有疑问!
# making up some similar data( adapted from earlier answer)
a <- rep ("Lefebvre Arnaud", 6)
b <- c("Abe Lyu", "Abe Lyu", "Lefebvre Arnaud", rep("De Dinechin Florent", 3))
df <- data.frame(CompleteName = a, CompleteName.1 = b)
which(df$CompleteName == df$CompleteName1)
#integer(0)
#Warning message:
#In is.na(e2) : is.na() applied to non-(list or vector) of type 'NULL'
str(df)
# 'data.frame': 6 obs. of 2 variables:
# $ CompleteName : Factor w/ 1 level "Lefebvre Arnaud": 1 1 1 1 1 1
# $ CompleteName.1: Factor w/ 3 levels "Abe Lyu","De Dinechin Florent",..: 1 1 3 2 2 2
stringsAsFactors
上面的 data.frame 不是用 stringsAsFactors=FALSE
构造的,因此导致了错误。不幸的是,开箱即用的 R
会将字符串强制转换为加载 csv
或创建 data.frame
的因素。这可以在创建 data.frame 时通过显式指定 stringsAsFactors=FALSE
df <- data.frame(CompleteName = a, CompleteName.1 = b, stringsAsFactors = FALSE)
df[which(df$CompleteName == df$CompleteName.1), ]
## CompleteName CompleteName.1
## 3 Lefebvre Arnaud Lefebvre Arnaud
为避免将来出现此问题,请在 R 会话开始时 运行 options(stringsAsFactors = FALSE)
(或将其放在 .R
脚本的顶部)。更多讨论在这里:
- disable stringsAsFactors
这是一个使用 data.table
的解决方案,与 data.frame
解决方案的性能比较基于与您的情况相同的记录数。
col1 = sample(x = letters, size = 354903, replace = TRUE)
col2 = sample(x = letters, size = 354903, replace = TRUE)
library(data.table)
dt = data.table(col1 = col1, col2 = col2)
df = data.frame(col1 = col1, col2 = col2)
# comparing the 2 columns
system.time(dt$col1==dt$col2)
system.time(df$col1==df$col2)
# storing the comparison in the table/frame itself
system.time(dt[, col3:= (col1==col2)])
system.time({df$col3 = (df$col1 == df$col2)})
data.table
方法在我的机器上提供了显着的加速:从 0.020 秒到 0.008 秒。
亲自尝试看看。我知道这对于如此少的行数来说并不是很重要,但是将其乘以 1000,您会看到很大的不同!