mat*_*sho 8 text r dplyr mutate
我试图计算源向量和tibble中的比较向量之间的Jaccard相似性.
首先,使用names_字段(字符串向量)创建一个tibble.使用dplyr的mutate,创建names_vec,列表列,其中每行现在是一个向量(向量的每个元素都是一个字母).
然后,使用列jaccard_sim创建一个新的tibble,它应该计算Jaccard相似度.
source_vec <- c('a', 'b', 'c')
df_comp <- tibble(names_ = c("b d f", "u k g", "m o c"),
names_vec = strsplit(names_, ' '))
df_comp_jaccard <- df_comp %>%
dplyr::mutate(jaccard_sim = length(intersect(names_vec, source_vec))/length(union(names_vec, source_vec)))
Run Code Online (Sandbox Code Playgroud)
jaccard_sim中的所有值都为零.但是,如果我们运行这样的东西,我们得到第一个条目的正确的Jaccard相似度为0.2:
a <- length(intersect(source_vec, df_comp[[1,2]]))
b <- length(union(source_vec, df_comp[[1,2]]))
a/b
Run Code Online (Sandbox Code Playgroud)
Moo*_*per 11
你可以简单地添加 rowwise
df_comp_jaccard <- df_comp %>%
rowwise() %>%
dplyr::mutate(jaccard_sim = length(intersect(names_vec, source_vec))/
length(union(names_vec, source_vec)))
# A tibble: 3 x 3
names_ names_vec jaccard_sim
<chr> <list> <dbl>
1 b d f <chr [3]> 0.2
2 u k g <chr [3]> 0.0
3 m o c <chr [3]> 0.2
Run Code Online (Sandbox Code Playgroud)
使用时,rowwise您可以获得最期望的直观行为mutate:"为每一行执行此操作".
不使用rowwise意味着你利用矢量化函数,这更快,这就是为什么它是默认值,但如果你不小心可能会产生意想不到的结果.
印象中mutate(或其他dplyr功能)的作品横行是一种假象,由于你与矢量函数工作的事实,其实你总是以饱满的列杂耍.
我将用几个例子来说明:
有时结果是相同的,使用矢量化函数,例如paste:
tibble(a=1:10,b=10:1) %>% mutate(X = paste(a,b,sep="_"))
tibble(a=1:10,b=10:1) %>% rowwise %>% mutate(X = paste(a,b,sep="_"))
# # A tibble: 5 x 3
# a b X
# <int> <int> <chr>
# 1 1 5 1_5
# 2 2 4 2_4
# 3 3 3 3_3
# 4 4 2 4_2
# 5 5 1 5_1
Run Code Online (Sandbox Code Playgroud)
有时它是不同的,具有未矢量化的功能,例如max:
tibble(a=1:5,b=5:1) %>% mutate(max(a,b))
# # A tibble: 5 x 3
# a b `max(a, b)`
# <int> <int> <int>
# 1 1 5 5
# 2 2 4 5
# 3 3 3 5
# 4 4 2 5
# 5 5 1 5
tibble(a=1:5,b=5:1) %>% rowwise %>% mutate(max(a,b))
# # A tibble: 5 x 3
# a b `max(a, b)`
# <int> <int> <int>
# 1 1 5 5
# 2 2 4 4
# 3 3 3 3
# 4 4 2 4
# 5 5 1 5
Run Code Online (Sandbox Code Playgroud)
请注意,在这种情况下,您不应该rowwise在现实生活中使用,但pmax为此目的进行了矢量化:
tibble(a=1:5,b=5:1) %>% mutate(pmax(a,b))
# # A tibble: 5 x 3
# a b `pmax(a, b)`
# <int> <int> <int>
# 1 1 5 5
# 2 2 4 4
# 3 3 3 3
# 4 4 2 4
# 5 5 1 5
Run Code Online (Sandbox Code Playgroud)
Intersect就是这样的函数,你给这个函数提供了一个包含向量和另一个向量的列表列,这两个对象没有交集.
我们可以map用来循环list
library(tidyverse)
df_comp %>%
mutate(jaccard_sim = map_dbl(names_vec, ~length(intersect(.x,
source_vec))/length(union(.x, source_vec))))
# A tibble: 3 x 3
# names_ names_vec jaccard_sim
# <chr> <list> <dbl>
#1 b d f <chr [3]> 0.2
#2 u k g <chr [3]> 0.0
#3 m o c <chr [3]> 0.2
Run Code Online (Sandbox Code Playgroud)
的map功能进行了优化.以下是system.time稍大的数据集
df_comp1 <- df_comp[rep(1:nrow(df_comp), 1e5),]
system.time({
df_comp1 %>%
rowwise() %>%
dplyr::mutate(jaccard_sim = length(intersect(names_vec, source_vec))/length(union(names_vec, source_vec)))
})
#user system elapsed
# 25.59 0.05 25.96
system.time({
df_comp1 %>%
mutate(jaccard_sim = map_dbl(names_vec, ~length(intersect(.x,
source_vec))/length(union(.x, source_vec))))
})
#user system elapsed
# 13.22 0.00 13.22
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4641 次 |
| 最近记录: |