我有一个 dataframe,它有很多列,类似于:
data <- data.frame (a.1 = 1:5, a.2b = 3:7, a.5 = 5:9, bt.16 = 4:8, bt.12342 = 7:11)
我希望得到一个结果,其中的列将具有相同前缀的变量相加。在本例中,我希望返回一个 Dataframe :a =(9:13),b =(11:15)我的真实的数据集要复杂得多(我想用不同的utm参数来合并网页的页面浏览量),但这种情况下的解决方案应该会让我走上正轨。
fwzugrvs1#
下面是一个以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
hec6srdp2#
你可以试试
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 package(v0.2.0)于2018年4月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
7jmck4yq3#
下面是另一个tidyverse解决方案:
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
uhry853o4#
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)]) ))
h4cxqtbf5#
使用base R的rowsum函数的一行方法如何:
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函数对由相同组标签索引的这些行求和。再次转置将数据返回到其原始形式,现在对具有相同标签的列求和。
5jdjgkvh6#
另一种解决方案是使用矩阵乘积:
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","b"), function(a,b){startsWith(b,a)}, colnames(data))
结果:
a b [1,] 9 11 [2,] 12 13 [3,] 15 15 [4,] 18 17 [5,] 21 19
这里sapply(c("a","b"), function(a,b){startsWith(b,a)}, colnames(data))是
sapply(c("a","b"), function(a,b){startsWith(b,a)}, colnames(data))
a b [1,] TRUE FALSE [2,] TRUE FALSE [3,] TRUE FALSE [4,] FALSE TRUE [5,] FALSE TRUE
表示列应该如何组合。注意,用这种方法可以很容易地保留数据的行名称。这里使用sapply来保存列名,否则您可以简单地使用outer(colnames(data), c("a","b"), startsWith),然后自己设置列名。
sapply
outer(colnames(data), c("a","b"), startsWith)
6条答案
按热度按时间fwzugrvs1#
下面是一个以R为底的溶液:
hec6srdp2#
你可以试试
由reprex package(v0.2.0)于2018年4月16日创建。
您还可以执行以下操作:
7jmck4yq3#
下面是另一个
tidyverse
解决方案:uhry853o4#
如果您有两个以上的前缀,您可以这样做:
h4cxqtbf5#
使用base R的
rowsum
函数的一行方法如何:其思想是将数据转置,使列变为行,然后应用
rowsum
函数对由相同组标签索引的这些行求和。再次转置将数据返回到其原始形式,现在对具有相同标签的列求和。5jdjgkvh6#
另一种解决方案是使用矩阵乘积:
结果:
这里
sapply(c("a","b"), function(a,b){startsWith(b,a)}, colnames(data))
是表示列应该如何组合。注意,用这种方法可以很容易地保留数据的行名称。
这里使用
sapply
来保存列名,否则您可以简单地使用outer(colnames(data), c("a","b"), startsWith)
,然后自己设置列名。