R语言 对名称相似的列按行求和

o8x7eapl  于 2023-01-15  发布在  其他
关注(0)|答案(6)|浏览(235)

我有一个 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参数来合并网页的页面浏览量),但这种情况下的解决方案应该会让我走上正轨。

fwzugrvs

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
hec6srdp

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
7jmck4yq

7jmck4yq3#

下面是另一个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
uhry853o

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)]) ))
h4cxqtbf

h4cxqtbf5#

使用base R的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函数对由相同组标签索引的这些行求和。再次转置将数据返回到其原始形式,现在对具有相同标签的列求和。

5jdjgkvh

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))

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),然后自己设置列名。

相关问题