jpm*_*m92 7 group-by aggregate r dplyr data-wrangling
考虑以下数据框:
\ndummy_df <- tibble(\n A=c("ABC", "ABC", "BCD", "CDF", "CDF", "CDF"),\n B=c(0.25, 0.25, 1.23, 0.58, 0.58, 0.58),\n C=c("lorem", "ipsum", "dolor", "amet", "something", "else"),\n D=c("up", "up", "down", "down", "down", "down"),\n E=c(132, 132, 243, 512, 512, 512),\n F=c("m1", "m1", "m5", "m3", "m3", "m3"),\n G=c("val", "val", "mur", "mad", "mad", "mad"),\n H=c("grx", "grx", "bcn", "sal", "sal", "sal"),\n I=c(1.68, 1.68, 2.31, 3.12, 3.12, 3.12),\n J=c("p", "p", "f", "p", "p", "p"),\n K=c(100, 100, 200, 143, 143, 143)\n)\n\n# A tibble: 6 \xc3\x97 11\n A B C D E F G H I J K\n <chr> <dbl> <chr> <chr> <dbl> <chr> <chr> <chr> <dbl> <chr> <dbl>\n1 ABC 0.25 lorem up 132 m1 val grx 1.68 p 100\n2 ABC 0.25 ipsum up 132 m1 val grx 1.68 p 100\n3 BCD 1.23 dolor down 243 m5 mur bcn 2.31 f 200\n4 CDF 0.58 amet down 512 m3 mad sal 3.12 p 143\n5 CDF 0.58 something down 512 m3 mad sal 3.12 p 143\n6 CDF 0.58 else down 512 m3 mad sal 3.12 p 143\nRun Code Online (Sandbox Code Playgroud)\n读完本文后,我成功折叠了 C 列,以便将 A 列的每个唯一行值的值连接成一个字符串。
\ndummy_df %>% group_by(A) %>% summarise(hits = toString(C), nhits=n())\n\n# A tibble: 3 \xc3\x97 3\n A hits nhits\n <chr> <chr> <int>\n1 ABC lorem, ipsum 2\n2 BCD dolor 1\n3 CDF amet, something, else 3\nRun Code Online (Sandbox Code Playgroud)\n但是,我丢失了对我来说至关重要的所有其他列信息。如何在折叠 C 列时保留有关所有列的信息?理想情况下,无需对列名称进行硬编码即可完成此操作,因为列数可能会根据数据集而变化。
\n我已阅读此内容,但显示的示例不会创建新变量,因此我无法使其工作。
\n这就是我正在寻找的:
\n# A tibble: 3 \xc3\x97 12\n A hits nhits B D E F G H I J K\n <chr> <chr> <int> <dbl> <chr> <dbl> <chr> <chr> <chr> <dbl> <chr> <dbl>\n1 ABC lorem, ipsum 2 0.25 up 132 m1 val grx 1.68 p 100\n2 BCD dolor 1 1.23 down 243 m5 mur bcn 2.31 f 200\n3 CDF amet, something, else 3 0.58 down 512 m3 mad sal 3.12 p 143\nRun Code Online (Sandbox Code Playgroud)\n
如果我们假设除C每个A组之外的所有字段都将包含重复值,那么我们可以这样做:
dummy_df %>%\n group_by(A) %>%\n summarize(\n nhits = n(),\n across(where(is.character), ~ toString(unique(.))),\n across(where(~ !is.character(.)), ~ unique(.))\n ) %>%\n ungroup()\n# # A tibble: 3 \xc3\x97 12\n# A nhits C D F G H J B E I K\n# <chr> <int> <chr> <chr> <chr> <chr> <chr> <chr> <dbl> <dbl> <dbl> <dbl>\n# 1 ABC 2 lorem, ipsum up m1 val grx p 0.25 132 1.68 100\n# 2 BCD 1 dolor down m5 mur bcn f 1.23 243 2.31 200\n# 3 CDF 3 amet, something, else down m3 mad sal p 0.58 512 3.12 143\nRun Code Online (Sandbox Code Playgroud)\n在这种情况下,由于所有其他变量都在重复,所以一切都保持原样。但是,如果我们有可变性,那么我设置了一个捕获,其中字符串组合(与toString)并且不同的数字导致重复行。
dummy_df$H[1] <- "GRX"\ndummy_df$K[1] <- 99\n %>%\n group_by(A) %>%\n summarize(\n nhits = n(),\n across(where(is.character), ~ toString(unique(.))),\n across(where(~ !is.character(.)), ~ unique(.))\n ) %>%\n ungroup()\n# A tibble: 4 \xc3\x97 12\n A nhits C D F G H J B E I K\n <chr> <int> <chr> <chr> <chr> <chr> <chr> <chr> <dbl> <dbl> <dbl> <dbl>\n1 ABC 2 lorem, ipsum up m1 val GRX, grx p 0.25 132 1.68 99\n2 ABC 2 lorem, ipsum up m1 val GRX, grx p 0.25 132 1.68 100\n3 BCD 1 dolor down m5 mur bcn f 1.23 243 2.31 200\n4 CDF 3 amet, something, else down m3 mad sal p 0.58 512 3.12 143\nRun Code Online (Sandbox Code Playgroud)\n该across函数迭代多个列。该where函数允许我们根据列的值对列进行子集化,对于character列,我们将应用toString,而对于其他列,我们将使用unique。这意味着字符串列永远不应该添加行,但非字符串可以。
类似数字的列的替代方法是使用first(.)代替unique(.),它将按组默默地丢弃每列中除第一个值之外的所有值。使用相同的修改数据,我们会看到这一点,其中关键区别在于自从第一个值是 以来K已经丢弃了这些值。10099
dummy_df %>%\n group_by(A) %>%\n summarize(\n nhits = n(), \n across(where(is.character), ~ toString(unique(.))),\n across(where(~ !is.character(.)), ~ first(.))\n ) %>%\n ungroup()\n# # A tibble: 3 \xc3\x97 12\n# A nhits C D F G H J B E I K\n# <chr> <int> <chr> <chr> <chr> <chr> <chr> <chr> <dbl> <dbl> <dbl> <dbl>\n# 1 ABC 2 lorem, ipsum up m1 val GRX, grx p 0.25 132 1.68 99\n# 2 BCD 1 dolor down m5 mur bcn f 1.23 243 2.31 200\n# 3 CDF 3 amet, something, else down m3 mad sal p 0.58 512 3.12 143\nRun Code Online (Sandbox Code Playgroud)\n如果您愿意,您也可以选择与字符串列一起使用first,这可以将逻辑简化为单个across:
dummy_df %>%\n group_by(A) %>%\n summarize(\n nhits = n(),\n across(everything(), ~ first(.))\n ) %>%\n ungroup()\n# # A tibble: 3 \xc3\x97 12\n# A nhits B C D E F G H I J K\n# <chr> <int> <dbl> <chr> <chr> <dbl> <chr> <chr> <chr> <dbl> <chr> <dbl>\n# 1 ABC 2 0.25 lorem up 132 m1 val GRX 1.68 p 99\n# 2 BCD 1 1.23 dolor down 243 m5 mur bcn 2.31 f 200\n# 3 CDF 3 0.58 amet down 512 m3 mad sal 3.12 p 143\nRun Code Online (Sandbox Code Playgroud)\n请注意,我们已经丢失了H("grx"因为"GRX"是第一个)以及K的值100。
data.table最后一个代码块的变体可以简单地是:
library(data.table)\nas.data.table(dummy_df)[, c(.(nhits = .N), lapply(.SD, first)), by = A]\nRun Code Online (Sandbox Code Playgroud)\n和基本的 R 演绎?也许不那么“漂亮”:-)
\nReduce(\n function(a, b) merge(a, b, by = "A", all = TRUE), \n list(\n setNames(aggregate(C ~ A, dummy_df, FUN = length), c("A", "nhits")), \n aggregate(C ~ A, dummy_df, FUN = toString),\n aggregate(. ~ A, subset(dummy_df, select = -C), FUN = function(z) z[1])\n )\n)\n# A nhits C B D E F G H I J K\n# 1 ABC 2 lorem, ipsum 0.25 up 132 m1 val GRX 1.68 p 99\n# 2 BCD 1 dolor 1.23 down 243 m5 mur bcn 2.31 f 200\n# 3 CDF 3 amet, something, else 0.58 down 512 m3 mad sal 3.12 p 143\nRun Code Online (Sandbox Code Playgroud)\n