每行对不同范围的列求和
Sum different range of columns per row
我想在我的数据集中创建一个新变量来对特定范围的列求和,但是要求和的列范围因每一行而异。
这是我的示例数据集。我想创建一个新变量 NUM1
,它是第 1 列到 ARRAYEND
的总和,其中变量 ARRAYEND
指定 NUM1
列的总和。
#create sample dataset
r1<-c(1,1,1,1,0,2)
r2<-c(1,1,0,1,1,4)
df<-as.data.frame(rbind(r1,r2))
names(df)<-c("Flag1","Flag2","Flag3","Flag4","Flag5","ARRAYEND")
Flag1 Flag2 Flag3 Flag4 Flag5 ARRAYEND
r1 1 1 1 1 0 2
r2 1 1 0 1 1 4
这是我想要的结果:
Flag1 Flag2 Flag3 Flag4 Flag5 ARRAYEND NUM1
r1 1 1 1 1 0 2 2
r2 1 1 0 1 1 4 3
我试图通过 dplyr
执行此操作,但它给我一个错误。
df <-df %>% mutate(NUM1 = rowSums(.[1:df$ARRAYEND]))
Warning messages:
1: Problem with `mutate()` input `NUM1`.
ℹ numerical expression has 2 elements: only the first used
ℹ Input `NUM1` is `rowSums(.[1:df$ARRAYEND])`.
2: In 1:df$ARRAYEND :
numerical expression has 2 elements: only the first used
A base R
选项将循环遍历具有 apply
和 MARGIN = 1
的行,然后获取 'ARRAYEND' 的 seq
uence,子集'x' 的元素并得到 sum
df$NUM1 <- apply(df, 1, function(x) sum(x[seq(x['ARRAYEND'])]))
-输出
df
# Flag1 Flag2 Flag3 Flag4 Flag5 ARRAYEND NUM1
#r1 1 1 1 1 0 2 2
#r2 1 1 0 1 1 4 3
注意:tidyverse
不保留行名。所以,使用 base R
可能会更好
如果我们想要 tidyverse
,一个选项是首先将行名作为列
library(tibble)
library(dplyr)
df %>%
rownames_to_column('rn') %>%
rowwise %>%
mutate(NUM1 = sum(c_across(starts_with("Flag"))[seq(ARRAYEND)])) %>%
ungroup %>%
column_to_rownames('rn')
-输出
# Flag1 Flag2 Flag3 Flag4 Flag5 ARRAYEND NUM1
#r1 1 1 1 1 0 2 2
#r2 1 1 0 1 1 4 3
另一个基本 R 选项使用 Reduce
transform(
df,
NUM1 = list2DF(Reduce("+", df, accumulate = TRUE))[cbind(seq_along(ARRAYEND), ARRAYEND)]
)
给予
Flag1 Flag2 Flag3 Flag4 Flag5 ARRAYEND NUM1
r1 1 1 1 1 0 2 2
r2 1 1 0 1 1 4 3
我想在我的数据集中创建一个新变量来对特定范围的列求和,但是要求和的列范围因每一行而异。
这是我的示例数据集。我想创建一个新变量 NUM1
,它是第 1 列到 ARRAYEND
的总和,其中变量 ARRAYEND
指定 NUM1
列的总和。
#create sample dataset
r1<-c(1,1,1,1,0,2)
r2<-c(1,1,0,1,1,4)
df<-as.data.frame(rbind(r1,r2))
names(df)<-c("Flag1","Flag2","Flag3","Flag4","Flag5","ARRAYEND")
Flag1 Flag2 Flag3 Flag4 Flag5 ARRAYEND
r1 1 1 1 1 0 2
r2 1 1 0 1 1 4
这是我想要的结果:
Flag1 Flag2 Flag3 Flag4 Flag5 ARRAYEND NUM1
r1 1 1 1 1 0 2 2
r2 1 1 0 1 1 4 3
我试图通过 dplyr
执行此操作,但它给我一个错误。
df <-df %>% mutate(NUM1 = rowSums(.[1:df$ARRAYEND]))
Warning messages:
1: Problem with `mutate()` input `NUM1`.
ℹ numerical expression has 2 elements: only the first used
ℹ Input `NUM1` is `rowSums(.[1:df$ARRAYEND])`.
2: In 1:df$ARRAYEND :
numerical expression has 2 elements: only the first used
A base R
选项将循环遍历具有 apply
和 MARGIN = 1
的行,然后获取 'ARRAYEND' 的 seq
uence,子集'x' 的元素并得到 sum
df$NUM1 <- apply(df, 1, function(x) sum(x[seq(x['ARRAYEND'])]))
-输出
df
# Flag1 Flag2 Flag3 Flag4 Flag5 ARRAYEND NUM1
#r1 1 1 1 1 0 2 2
#r2 1 1 0 1 1 4 3
注意:tidyverse
不保留行名。所以,使用 base R
如果我们想要 tidyverse
,一个选项是首先将行名作为列
library(tibble)
library(dplyr)
df %>%
rownames_to_column('rn') %>%
rowwise %>%
mutate(NUM1 = sum(c_across(starts_with("Flag"))[seq(ARRAYEND)])) %>%
ungroup %>%
column_to_rownames('rn')
-输出
# Flag1 Flag2 Flag3 Flag4 Flag5 ARRAYEND NUM1
#r1 1 1 1 1 0 2 2
#r2 1 1 0 1 1 4 3
另一个基本 R 选项使用 Reduce
transform(
df,
NUM1 = list2DF(Reduce("+", df, accumulate = TRUE))[cbind(seq_along(ARRAYEND), ARRAYEND)]
)
给予
Flag1 Flag2 Flag3 Flag4 Flag5 ARRAYEND NUM1
r1 1 1 1 1 0 2 2
r2 1 1 0 1 1 4 3