[英]Combine/sort columns with dplyr and/or 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(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,但到目前為止我仍不知道該怎么做。
網絡/ igraph選項比“ t(apply(”選項)要快,但是我仍然需要將圖形轉換回data.table進行進一步分析。
關於如何使用dplyr或tidyr運行“ t(apply(”)選項的任何想法嗎?
在基數R中,我們可以使用非公式接口將akrun的pmin
和pmax
建議與aggregate
結合起來,如下所示:
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倍。
數據
df <-
structure(list(From = c("A", "A", "C", "B"), To = c("B", "C",
"A", "C"), count = c(2L, 1L, 3L, 1L)), .Names = c("From", "To",
"count"), class = "data.frame", row.names = c(NA, -4L))
更大的樣本數據
set.seed(1234)
df <- data.frame(From=sample(LETTERS, 9e6, replace=TRUE),
To=sample(LETTERS, 9e6, replace=TRUE),
count=sample(100, 9e6, replace=TRUE),
stringsAsFactors=FALSE)
我們可以使用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
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))
最后要計數並確保輸出列是因子(因為akrun指出行排序前后的因子水平很容易會有所不同)。
df_out %>%
dplyr::count(key, name = "count") %>%
tidyr::separate(key, sep = "_", into = out_cols) %>%
dplyr::mutate_at(out_cols, as.factor)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.