函数从数据框中的先前列中连续减去列并保存在新数据框中

问题描述 投票:0回答:5

H,我是 R 的新手,我正在尝试编写一个函数来创建一个新的数据框,该数据框描述了减去原始数据集中彼此相邻的每两列的结果。想象一下这是可能的数据(尽管我有很多变量)

obs  var1   var2   var3    
1     5      10     14   
2     6      11     15   
3     7      12     16   
4     8      13     17    

输出应该是这个样子

obs var2_1 var3_2
1     5       4
2     5       4
3     5       4
4     5       4

非常感谢您!

r dataframe multiple-columns difference
5个回答
2
投票

这基本上是-

df[-c(1, 2)] - df[-c(1, ncol(df))] 

#  var2 var3
#1    5    4
#2    5    4
#3    5    4
#4    5    4

使其更具可扩展性并符合您的预期输出 -

#Create a temporary dataframe to keep only the columns we are interested in
temp_df <- df[-1]
#Save ncol value in a variable to avoid recalculating
n <- ncol(temp_df)
#Create new column names
new_cols <- paste0('var', 2:n,'_', 1:(n-1))
#add the calculated columns to temporary df
temp_df[new_cols] <- temp_df[-1] - temp_df[-n]
#keeping only interested columns. 
cbind(df[1], temp_df[new_cols])

#  obs var2_1 var3_2
#1   1      5      4
#2   2      5      4
#3   3      5      4
#4   4      5      4

1
投票

@Mael 的答案肯定更紧凑,但您也可以使用

dplyr
:

您可以创建一个变量名向量,这些变量名将参与减法。然后,从第二个开始循环遍历名称。您可以创建一个变量,即第 i 个减去前一个。

library(dplyr)
dat <- tibble::tribble(
  ~obs,  ~var1,   ~var2,   ~var3,    
1,     5,      10,     14,   
2,     6,      11,     15,   
3,     7,      12,     16,   
4,     8,      13,     17)   

ndat <- names(dat)
## remove obs from list of variables
ndat <- ndat[-1]
for(i in 2:length(ndat)){
  newvar <- paste(ndat[i], ndat[(i-1)], sep="_")
  dat <- dat %>% 
    mutate( {{newvar}} := .data[[ndat[i]]] - .data[[ndat[(i-1)]]])
}
dat %>% select(-all_of(ndat))
#> # A tibble: 4 × 3
#>     obs var2_var1 var3_var2
#>   <dbl>     <dbl>     <dbl>
#> 1     1         5         4
#> 2     2         5         4
#> 3     3         5         4
#> 4     4         5         4

创建于 2023-03-01 与 reprex v2.0.2


1
投票

一个

dplyr
解决方案:

library(dplyr)

df %>%
  mutate(pick(var2:var3) - pick(var1:var2), .keep = "unused")

#   obs var2 var3
# 1   1    5    4
# 2   2    5    4
# 3   3    5    4
# 4   4    5    4

0
投票

您可以使用

apply
进行逐行差异。第二个参数
1
表示函数
diff
应用于行。如果需要,转换为
data.frame

cbind(df[1], t(apply(df[-1], 1, diff)))

  obs var2 var3
1   1    5    4
2   2    5    4
3   3    5    4
4   4    5    4

0
投票

也可以通过旋转来实现:

library(dplyr)
library(tidyr)

df |>
  pivot_longer(-obs, names_prefix = "var") |>
  mutate(name = paste0("var", name, "_", lag(name)),
         value = value-lag(value),
         .by = "obs") |>
  na.omit() |>
  pivot_wider(id_cols = obs)

输出:

# A tibble: 4 × 3
    obs var2_1 var3_2
  <dbl>  <dbl>  <dbl>
1     1      5      4
2     2      5      4
3     3      5      4
4     4      5      4
© www.soinside.com 2019 - 2024. All rights reserved.