我有一个数据框,其中有很多类似于以下内容的列:
data <- data.frame (a.1 = 1:5, a.2b = 3:7, a.5 = 5:9, bt.16 = 4:8, bt.12342 = 7:11)
我希望得到一个结果,其中的列将相同前缀的变量求和。在这个例子中,我想返回一个数据框: a = (9:13),bt = (11:15)
我的真实数据集要复杂得多(我想将具有不同utm参数的网页的页面浏览次数组合起来),但是此案例的解决方案应该能让我上正确的轨道。
以下是使用 R 语言基础解决方案:
> prefixes = unique(sub("\\..*", "", colnames(data)))
> sapply(prefixes, function(x)rowSums(data[,startsWith(colnames(data), x)]))
a bt
[1,] 9 11
[2,] 12 13
[3,] 15 15
[4,] 18 17
[5,] 21 19
您可以尝试
library(tidyverse)
data.frame (a.1 = 1:5, a.2b = 3:7, a.5 = 5:9, bt.16 = 4:8, bt.12342 = 7:11) %>%
rownames_to_column() %>%
gather(k, v, -rowname) %>%
separate(k, letters[1:2]) %>%
group_by(rowname, a) %>%
summarise(Sum=sum(v)) %>%
spread(a, Sum)
#> # A tibble: 5 x 3
#> # Groups: rowname [5]
#> rowname a bt
#> <chr> <int> <int>
#> 1 1 9 11
#> 2 2 12 13
#> 3 3 15 15
#> 4 4 18 17
#> 5 5 21 19
这段文字是使用 reprex包 (v0.2.0) 在2018-04-16创建的。
你也可以进行以下操作:
data.frame (a.1 = 1:5, a.2b = 3:7, a.5 = 5:9, bt.16 = 4:8, bt.12342 = 7:11) %>%
rownames_to_column() %>%
pivot_longer(-1, names_to = c(".value", "set"), names_sep = "[.]") %>%
group_by(rowname) %>%
summarise(across(a:bt,sum, na.rm=T))
# A tibble: 5 x 3
rowname a bt
<chr> <int> <int>
1 1 9 11
2 2 12 13
3 3 15 15
4 4 18 17
5 5 21 19
这里有另一个 tidyverse
的解决方案:
library(tidyverse)
t(data) %>%
data.frame() %>%
group_by(., id = gsub('\\..*', '', rownames(.))) %>%
summarise_all(sum) %>%
data.frame() %>%
column_to_rownames(var = 'id') %>%
t()
结果:
a bt
X1 9 11
X2 12 13
X3 15 15
X4 18 17
X5 21 19
data <- data.frame (a.1 = 1:5, a.2b = 3:7, a.5 = 5:9, bt.16 = 4:8, bt.12342 = 7:11)
i <- grepl("a.", names(data), fixed = TRUE)
result <- data.frame(a=rowSums(data[, i]), bt=rowSums(data[, !i]))
result
# > result
# a bt
# 1 9 11
# 2 12 13
# 3 15 15
# 4 18 17
# 5 21 19
prefs <- c("a.", "bt.")
as.data.frame(lapply(prefs, function(p) rowSums(data[, grepl(p, names(data), fixed = TRUE)]) ))
rowsum
函数来实现一行代码的方法:> t(rowsum(t(data), group = sub("\\..*", "", colnames(data))))
a bt
[1,] 9 11
[2,] 12 13
[3,] 15 15
[4,] 18 17
[5,] 21 19
这个想法是将数据转置,使列变成行,然后应用rowsum
函数对由相同组标签索引的这些行进行求和。再次转置将数据返回到其原始形式,现在具有相同标签的列已经被加总。
data <- data.frame (a.1 = 1:5, a.2b = 3:7, a.5 = 5:9, bt.16 = 4:8, bt.12342 = 7:11)
as.matrix(data) %*% sapply(c("a","bt"), function(a,b){startsWith(b,a)}, colnames(data))
结果:
a bt
[1,] 9 11
[2,] 12 13
[3,] 15 15
[4,] 18 17
[5,] 21 19
这里的sapply(c("a","bt"), function(a,b){startsWith(b,a)}, colnames(data))
是什么意思?
a bt
[1,] TRUE FALSE
[2,] TRUE FALSE
[3,] TRUE FALSE
[4,] FALSE TRUE
[5,] FALSE TRUE
表示如何合并列。请注意,通过这种方式,您可以轻松地保留数据的行名称。
在这里,使用sapply
来保留列名,否则您可以简单地使用outer(colnames(data), c("a","bt"), startsWith)
,然后自己设置列名。
library(magrittr); lapply(c("a","bt"), function(x) rowSums(data[, grepl(x, names(data))])) %>% setNames(., c("a","bt")) %>% data.frame
- Mike H.tidyverse
函数中的select(data,starts_with("prefix"))
吗? - Aramis7dstartsWith(names(data), x)
而不是grepl(x, names(data))
。 - IceCreamToucan