使用dplyr和/或tidyr组合/排序列
编辑:我尝试了下面的解决方案,但由于我需要将因子转换为字符并返回到因子,我丢失了一些重要信息 有了这张桌子,我想把它从这里分类使用dplyr和/或tidyr组合/排序列,r,dplyr,igraph,tidyr,R,Dplyr,Igraph,Tidyr,编辑:我尝试了下面的解决方案,但由于我需要将因子转换为字符并返回到因子,我丢失了一些重要信息 有了这张桌子,我想把它从这里分类 From To count A B 2 A C 1 C A 3 B C 1 对此, From To count 1 A B 2 2 A C 4 3 B C 1 到目前为止,我看到两种选择,一种是: df[1:2] <- t
From To count
A B 2
A C 1
C A 3
B C 1
对此,
From To count
1 A B 2
2 A C 4
3 B C 1
到目前为止,我看到两种选择,一种是:
df[1:2] <- t(apply(df[1:2], 1, sort))
aggregate(count ~ From + To, df, sum)
这是相当缓慢的,因为我正在处理9.000.000个观察值。或者简单地将其转换为iGraph网络,并合并边
g <- graph_from_data_frame(df, directed = TRUE, vertices = nodes)
g <- as.undirected(g, mode = "mutual", edge.attr.comb=list(weight = "sum"))
我遇到的两个问题是,我提到的第一个选项实际上应该使用dplyr或tidyr,但到目前为止我还不知道如何使用它
network/igraph选项比tapply选项快,但我仍然需要将该图转换回data.table以进行进一步分析
有没有关于如何使用dplyr或tidyr运行tapply选项的想法 我们可以使用pmin/pmax。应该快一点
library(dplyr)
df1 %>%
group_by(From1 = pmin(From, To), To = pmax(From, To)) %>%
summarise(count = sum(count)) %>%
rename(From = From1)
# From To count
# <chr> <chr> <int>
#1 A B 2
#2 A C 4
#3 B C 1
我们可以使用pmin/pmax。应该快一点
library(dplyr)
df1 %>%
group_by(From1 = pmin(From, To), To = pmax(From, To)) %>%
summarise(count = sum(count)) %>%
rename(From = From1)
# From To count
# <chr> <chr> <int>
#1 A B 2
#2 A C 4
#3 B C 1
在base R中,我们可以使用非公式界面将akrun的pmin和pmax建议与聚合结合起来,如下所示:
aggregate(df$count, list(From=pmin(df$From, df$To), To=pmax(df$From, df$To)), sum)
From To x
1 A B 2
2 A C 4
3 B C 1
注意,这要求df$From和df$To是字符向量,而不是因子
时间安排
此方法比使用apply更快,因为它不涉及到矩阵的转换。使用下面较大的数据集,通过900万次观察,在我的计算机上使用pmin和pmax和aggregate完成的时间为14.5秒,而OP使用apply的方法需要442.2秒或30倍
资料
大样本数据
在base R中,我们可以使用非公式界面将akrun的pmin和pmax建议与聚合结合起来,如下所示:
aggregate(df$count, list(From=pmin(df$From, df$To), To=pmax(df$From, df$To)), sum)
From To x
1 A B 2
2 A C 4
3 B C 1
注意,这要求df$From和df$To是字符向量,而不是因子
时间安排
此方法比使用apply更快,因为它不涉及到矩阵的转换。使用下面较大的数据集,通过900万次观察,在我的计算机上使用pmin和pmax和aggregate完成的时间为14.5秒,而OP使用apply的方法需要442.2秒或30倍
资料
大样本数据
不幸的是,我得到了以下错误:错误:向无效对象添加类因子。@FilipeTeixeira我认为From/to列是字符类。因此,您可以对每个字符进行df1%>%的变异,从:到%>%group\U by…非常有效。谢谢。不幸的是,我发现这个方法还有另一个问题。将变量变为字符,再变回因子,意味着我失去了初始级别。我可以创建一个查找表,但这里的想法实际上是有一个更简单、更快的代码。@FilipeTeixeira获得初始级别将很困难,因为我们正在更改值。例如,在您的eexample中,第一列的级别为“A”、“C”、“B”,但在输出中,“C”不存在,类似地,在“ToUnfortute”中,我遇到以下错误:错误:将类因子添加到无效对象。@Filipetixeira我认为From/to列是字符类。因此,您可以对每个字符进行df1%>%的变异,从:到%>%group\U by…非常有效。谢谢。不幸的是,我发现这个方法还有另一个问题。将变量变为字符,再变回因子,意味着我失去了初始级别。我可以创建一个查找表,但这里的想法实际上是有一个更简单、更快的代码。@FilipeTeixeira获得初始级别将很困难,因为我们正在更改值。例如,在您的eexample中,第一列的级别为'A'、'C'、'B',但在输出中,'C'不在那里,类似地,在'To@Imo非常感谢。我与基地的问题是,它是我的9.000.000观察缓慢的事实。下面的解决方案以应有的速度运行。请查看我的更新,其中包括时间安排。通常情况下,是某个特定的实现速度慢,而不是以R为基础。@Imo,但它同样会导致因素问题,我稍后需要这些因素进行数据验证。@Imo谢谢。我与基地的问题是,它是我的9.000.000观察缓慢的事实。下面的解决方案以应有的速度运行。请查看我的更新,其中包括时间安排。通常情况下,是某个特定的实现速度慢,而不是基于R本身,但它会再次导致因素问题,稍后我将需要这些因素进行数据验证。
library(tidyverse)
cols_before_merge <- c("From", "To")
out_cols <- c("col_1", "col_2")
df <- tibble::tribble(
~From, ~To, ~count,
"A", "B", 2,
"A", "C", 1,
"C", "A", 3,
"B", "C", 1,
)
df_out <- df %>%
dplyr::mutate(
key = purrr::pmap_chr(
list(From, To),
~ stringr::str_c(stringr::str_sort(c(...)), collapse = "_")
)
)
merge_sort <- function(cols_values) {
purrr::pmap_chr(
cols_values,
~ stringr::str_c(stringr::str_sort(c(...)), collapse = "_")
)
}
add_key <- function(cols) {
# column names need to be evaluated using the dataframe as an environment
cols_quosure <- rlang::enquo(cols)
# column names should be symbols not strings
cols_syms <- rlang::syms(cols)
cols_values <- purrr::map(
cols_syms,
~ rlang::eval_tidy(.x, rlang::quo_get_env(cols_quosure))
)
merge_sort(cols_values)
}
# Adding columns for key construction programmatically
df_out <- df %>%
dplyr::mutate(key = add_key(cols_before_merge))
df_out %>%
dplyr::count(key, name = "count") %>%
tidyr::separate(key, sep = "_", into = out_cols) %>%
dplyr::mutate_at(out_cols, as.factor)