假设我下面有一个tibble数据,我想要做的是计算(x 2
,x 3
)的最大值然后减去x 1
,其中x可以是或b。在我的真实数据中,我有超过3列,所以像2:n(例如,2:3)这样的东西会很棒。尝试了很多东西,似乎没有按照我的要求工作,仍然在努力处理字符串与列名称的事情。
dat <- tibble(`a 1` = c(0, 0, 0), `a 2` = 1:3, `a 3` = 3:1,
`b 1` = rep(1, 3), `b 2` = 4:6, `b 3` = 6:4)
foo <- function(x = 'a')
{
???
}
最终结果:
if x == `a`
c(3, 2, 3)
if x == `b`
c(5, 4, 5)
答案 0 :(得分:4)
此解决方案仅使用基础R.想法是定义一个函数(max_minus_first
)来计算答案。 max_minus_first
函数有两个参数。第一个参数dat
是用于分析的数据框,其格式与提供的OP相同。 group
是分析组的名称。最终产品是一个答案的矢量。
max_minus_first <- function(dat, group){
# Get all column names with starting string "group"
col_names <- colnames(dat)
dat2 <- dat[, col_names[grepl(paste0("^", group), col_names)]]
# Get the maximum values from all columns except the first column
max_value <- apply(dat2[, -1], 1, max, na.rm = TRUE)
# Calculate max_value minus the values from the first column
final_value <- max_value - unlist(dat2[, 1], use.names = FALSE)
return(final_value)
}
max_minus_first(dat, "a")
# [1] 3 2 3
max_minus_first(dat, "b")
# [1] 5 4 5
使用tidyverse
的解决方案。最终产品(dat2
)是tibble
,其中包含每个组的输出(a
,b
,...)
library(tidyverse)
dat2 <- dat %>%
rowid_to_column() %>%
gather(Column, Value, -rowid, -ends_with(" 1")) %>%
separate(Column, into = c("Group", "Column_Number")) %>%
gather(Column_1, Value_1, ends_with(" 1")) %>%
separate(Column_1, into = c("Group_1", "Column_Number_1")) %>%
filter(Group == Group_1) %>%
group_by(rowid, Group, Value_1) %>%
summarise(Value = max(Value, na.rm = TRUE)) %>%
mutate(Final = Value - Value_1) %>%
ungroup() %>%
select(-starts_with("Value")) %>%
spread(Group, Final)
dat2
# # A tibble: 3 x 3
# rowid a b
# * <int> <dbl> <dbl>
# 1 1 3 5
# 2 2 2 4
# 3 3 3 5
rowid_to_column()
来自tibble
包,是一种基于行ID创建新列的方法。gather
来自tidyr
包,用于将数据框从宽格式转换为长格式。我使用gather
两次,因为每个组的第一列与同一组中的其他列不同。 ends_with(" 1")
是来自select
的{{1}}辅助函数,它选择名称以dplyr
结尾的列。请注意" 1"
中的空格非常重要,因为如果存在此类列," 1"
可能会选择其他列,例如"1"
。a 11
来自separate
包,将列分为两列。我用它来分隔每个tidyr
中的Group
名称和列号。Group
将使用filter(Group == Group_1)
过滤行。Group == Group_1
然后group_by(rowid, Group, Value_1)
确保计算每个summarise(Value = max(Value, na.rm = TRUE))
的最大值。Group
用于计算每个mutate(Final = Value - Value_1)
的最大值与第一列的值之间的差值。结果存储在Group
列中。Final
会删除名称以select(-starts_with("Value"))
开头的所有列。"Value"
包的spread
将数据框从长格式转换为宽格式。另一个tidyr
解决方案,类似于解决方案2.它使用tidyverse
对每个do
进行操作,从而使代码更简洁。
Group