假设我有一个像这样的数据框:
df<-data.frame(A.1=1:5,B.1=2:6,C.1=3:7,
D.2=4:8,E.2=5:9,F.2=6:10)
df
A.1 B.1 C.1 D.2 E.2 F.2
1 1 2 3 4 5 6
2 2 3 4 5 6 7
3 3 4 5 6 7 8
4 4 5 6 7 8 9
5 5 6 7 8 9 10
我想要的是rowSums()
的组矢量,它是df
的列名,不带字母(例如c(1,1,1,2,2,2)
),输出为:
1 2
[1,] 6 15
[2,] 9 18
[3,] 12 21
[4,] 15 24
[5,] 18 27
我的真实数据集有来自18个小组的超过110K cols
,并且会找到一种优雅而简单的方法来实现它。
答案 0 :(得分:2)
由于data.frame
的内部构造方式,行操作通常比列操作慢得多。给定您对data.frame
实际大小的评论,我可能会使用data.table
将其转换为long,将组作为其自己的变量隔离,并进行按组求和。
df <- data.frame(
A.1 = 1:5,
B.1 = 6:10,
C.2 = 11:15,
D.2 = 16:20
)
首先,使用data.frame
将data.table
转换为setDT
。
library(data.table)
setDT(df)
然后,添加一个row_number
列(:=
创建一个新列; .N
是一个特殊变量,包含表中的行数)。
df[, row_number := 1:.N]
使用data.table
作为唯一ID列,将其转换为“长” row_number
。
df_long <- melt(df, id.vars = "row_number")
df_long
#> row_number variable value
#> 1: 1 A.1 1
#> 2: 2 A.1 2
#> 3: 3 A.1 3
#> 4: 4 A.1 4
#> 5: 5 A.1 5
#> 6: 1 B.1 6
#> 7: 2 B.1 7
#> 8: 3 B.1 8
#> 9: 4 B.1 9
#> 10: 5 B.1 10
#> 11: 1 C.2 11
#> 12: 2 C.2 12
#> 13: 3 C.2 13
#> 14: 4 C.2 14
#> 15: 5 C.2 15
#> 16: 1 D.2 16
#> 17: 2 D.2 17
#> 18: 3 D.2 18
#> 19: 4 D.2 19
#> 20: 5 D.2 20
创建一个新的group
列,该列应位于“。”之后。在新的“变量”列中(^.*?\\.
是从字符串开头到第一个“。”的所有内容; gsub(pattern, "", variable)
从pattern
中删除了variable
)。
df_long[, group := as.integer(gsub("^.*?\\.", "", variable))]
df_long
#> row_number variable value group
#> 1: 1 A.1 1 1
#> 2: 2 A.1 2 1
#> 3: 3 A.1 3 1
#> 4: 4 A.1 4 1
#> 5: 5 A.1 5 1
#> 6: 1 B.1 6 1
#> 7: 2 B.1 7 1
#> 8: 3 B.1 8 1
#> 9: 4 B.1 9 1
#> 10: 5 B.1 10 1
#> 11: 1 C.2 11 2
#> 12: 2 C.2 12 2
#> 13: 3 C.2 13 2
#> 14: 4 C.2 14 2
#> 15: 5 C.2 15 2
#> 16: 1 D.2 16 2
#> 17: 2 D.2 17 2
#> 18: 3 D.2 18 2
#> 19: 4 D.2 19 2
#> 20: 5 D.2 20 2
最后,按sum(value)
和row_number
对group
进行分组。
在data.table
中,这类操作非常快,比基本R更快,更高效。
df_long[, sum(value), by = list(row_number, group)]
#> row_number group V1
#> 1: 1 1 7
#> 2: 2 1 9
#> 3: 3 1 11
#> 4: 4 1 13
#> 5: 5 1 15
#> 6: 1 2 27
#> 7: 2 2 29
#> 8: 3 2 31
#> 9: 4 2 33
#> 10: 5 2 35
答案 1 :(得分:2)
rowsum
可以做到:
t(rowsum(t(df), c(1,1,1,2,2,2)))
1 2
[1,] 6 15
[2,] 9 18
[3,] 12 21
[4,] 15 24
[5,] 18 27
(出于任何原因,都没有colsum
。)
答案 2 :(得分:0)
使用库dplyr
和reshape2
。您可以逐行执行(无需尾随%>%来理解转换。基本思想是将melt
转换为整齐(高)格式以操纵行,然后将dcast
转换回宽格式
library(dplyr)
library(reshape2)
df %>%
# assign a row number for later grouping
mutate(rn=row_number()) %>%
# make into a tall data frame, with rn as the row key
melt(id.vars = "rn") %>%
# calculate the row suffix for grouping
mutate(suffix = str_extract(variable, "\\d+")) %>%
# put it back into a dataframe, summing value (could use acast if you want an array)
dcast(rn ~ suffix, value.var="value", fun.aggregate = sum)
# rn 1 2
# 1 1 6 15
# 2 2 9 18
# 3 3 12 21
# 4 4 15 24
# 5 5 18 27
答案 3 :(得分:0)
使用dplyr
:
new_df <- df %>%
mutate(ones = rowSums(select(., grep(".1", names(df), value = TRUE))),
twos = rowSums(select(., grep(".2", names(df), value = TRUE)))) %>%
select(ones, twos)
new_df
ones twos
1 6 15
2 9 18
3 12 21
4 15 24
5 18 27