大家好,感谢您的阅读。
我一直在尝试创建一个函数,该函数将迭代地减去两列的值并将该值粘贴到新列中。为了显示我的意思,这是一个带有初始数据集的示例:
Sample g1 g2 g3 g4 g5
s001 5 10 15 20 25
s002 6 11 16 21 26
s003 7 12 17 22 27
s004 8 13 18 23 28
假设我要选择g3。然后,我想从g3中减去所有其他列,但将值显示在每列旁边的新列中。本质上,最终结果将如下所示:
Sample g1 g1dt g2 g2dt g3 g3dt g4 g4dt g5dt g5dt
s001 5 10 10 5 15 0 20 -5 25 -10
s002 6 10 11 5 16 0 21 -5 26 -10
s003 7 10 12 5 17 0 22 -5 27 -10
s004 8 10 13 5 18 0 23 -5 28 -10
我尝试过的代码如下:
for (i in 2:6) {
dt <- paste0(names(dataset)[i]) #where names(dataset) is the ith name
#from dataset
dataset[[dt]] <- dataset$g3 - dataset[[,2:6]] #[[]] is
#supposed to create a new column "dt" added as a suffix
}
但这会导致以下错误:
Error in .subset2(x, ..2, exact = exact) :
recursive indexing failed at level 3
对我可以尝试的方法有任何想法吗?如果需要清除任何令人困惑的问题,请告诉我。谢谢!
答案 0 :(得分:3)
我们可以使用Thanks,
Bala.
:
mutate_at
结果:
library(dplyr)
myfun <- function(DF, col){
col_quo <- enquo(col)
DF %>%
mutate_at(vars(-Sample), funs(dt = !!col_quo - .)) %>%
select(Sample, sort(current_vars())) %>%
rename_all(funs(sub("_", "", .)))
}
myfun(df, g3)
注释:
Sample g1 g1dt g2 g2dt g3 g3dt g4 g4dt g5 g5dt
1 s001 5 10 10 5 15 0 20 -5 25 -10
2 s002 6 10 11 5 16 0 21 -5 26 -10
3 s003 7 10 12 5 17 0 22 -5 27 -10
4 s004 8 10 13 5 18 0 23 -5 28 -10
将作为参数提供的表达式转换为quosure。稍后在enquo
步骤中使用!!
对它进行评估。
mutate_at
将函数应用于mutate_at
中指定的thes列。如果像我一样vars
那样将输出设置为变量,则会以dt = g3 - .
为后缀自动创建新列。
由于OP表示他希望每个输出列都紧靠原始列,因此我们可以_dt
sort
并使用current_vars()
来设置正确的列顺序,同时保持{ {1}}第一列。
最后一个select
步骤是可选的,但是如果我们不希望Sample
成为后缀的一部分,则可以使用rename_all
和_
从列名称中删除所有rename_all
。
数据:
sub
答案 1 :(得分:2)
这将做您想要的。请注意,根据您的示例,myfun
将第一列视为特殊列。
# example data
df <- data.frame(
Sample = paste0("s00", 1:4),
g1 = 5:8,
g2 = 10:13,
g3 = 15:18,
g4 = 20:23,
g5 = 25:28,
stringsAsFactors = FALSE
)
# function to do what you want
myfun <- function(x, df) {
mat <- df[[x]] - as.matrix(df[ , names(df)[-1]]) #subtract all cols from x
colnames(mat) <- paste0(names(df)[-1], "dt") #give these new cols names
df <- cbind(df, mat) #add new cols to dataframe
df <- df[ , c(1, order(names(df)[-1])+1)] #reorder cols
return(df)
}
# test it
myfun("g3", df)
# result
Sample g1 g1dt g2 g2dt g3 g3dt g4 g4dt g5 g5dt
1 s001 5 10 10 5 15 0 20 -5 25 -10
2 s002 6 10 11 5 16 0 21 -5 26 -10
3 s003 7 10 12 5 17 0 22 -5 27 -10
4 s004 8 10 13 5 18 0 23 -5 28 -10
答案 2 :(得分:1)
这里是一种可能的dplyr
解决方案:
library(dplyr)
# reproduce your data frame
df <- data_frame(
Sample = c("s001", "s002", "s003", "s004"),
g1 = 5:8,
g2 = 10:13,
g3 = 15:18,
g4 = 20:23,
g5 = 25:28
)
# compute the differences and arrange the order of columns
df %>%
mutate(
g1dt = g3 - g1,
g2dt = g3 - g2,
g3dt = g3 - g3,
g4dt = g3 - g4,
g5dt = g3 - g5,
) %>%
select(1, 2, 7, 3, 8, 4, 9, 5, 10, 6, 11)
# # A tibble: 4 x 11
# Sample g1 g1dt g2 g2dt g3 g3dt g4 g4dt g5 g5dt
# <chr> <int> <int> <int> <int> <int> <int> <int> <int> <int> <int>
# 1 s001 5 10 10 5 15 0 20 -5 25 -10
# 2 s002 6 10 11 5 16 0 21 -5 26 -10
# 3 s003 7 10 12 5 17 0 22 -5 27 -10
# 4 s004 8 10 13 5 18 0 23 -5 28 -10
答案 3 :(得分:0)
您可以简单地创建一个新的数据框并从特定列中删除值。
df_new <- - df[, 2:6] + df[, 4] # calculate subtractions
colnames(df_new) <- paste0(colnames(df_new), "dt")
df <- cbind(df, df_new)
此解决方案避免了无效循环,并且具有可伸缩性(您可以根据需要添加任意列)。
如果列的顺序对您来说很重要,则只需按名称排序即可;该解决方案符合您的列命名:
df <- df[, order(colnames(df))]
答案 4 :(得分:0)
以R
为基础:
fun <- function(df,x) {
df[paste0(names(df)[-1],"dt")] <- df[["g3"]] - df[-1]
df
}
fun(df,"g3")
# Sample g1 g2 g3 g4 g5 g1dt g2dt g3dt g4dt g5dt
# 1 s001 5 10 15 20 25 10 5 0 -5 -10
# 2 s002 6 11 16 21 26 10 5 0 -5 -10
# 3 s003 7 12 17 22 27 10 5 0 -5 -10
# 4 s004 8 13 18 23 28 10 5 0 -5 -10
数据
df <- read.table(text="Sample g1 g2 g3 g4 g5
s001 5 10 15 20 25
s002 6 11 16 21 26
s003 7 12 17 22 27
s004 8 13 18 23 28",strin=F,h=T)