繁体   English   中英

减去相似的列名 R

[英]Subtracting similar column names R

我有一个数据框,其中包含 'x1' 和 'x1_fit' 的列,在某些情况下,数字高达 5。

date <- seq(as.Date('2019-11-04'), by = "days", length.out = 7)
x1 <- c(100,120,111,152,110,112,111)
x1_fit <- c(150,142,146,148,123,120,145)
x2 <- c(110,130,151,152,150,142,161)
x2_fit <- c(170,172,176,178,173,170,175)

df <- data.frame(date,x1,x1_fit,x2,x2_fit)

我该怎么做 x1_fit - x1 等等。 x 的数量每次都会改变。

您可以使用正则表达式选择那些列(假设列的顺序合适):

> df[, grep('^x\\d+_fit$', colnames(df))] - df[, grep('^x\\d+$', colnames(df))]
  x1_fit x2_fit
1     50     60
2     22     42
3     35     25
4     -4     26
5     13     23
6      8     28
7     34     14

如果要将差异分配给原始df

df[, paste0(grep('^x\\d+$', colnames(df), value = TRUE), '_diff')] <- 
    df[, grep('^x\\d+_fit$', colnames(df))] - df[, grep('^x\\d+$', colnames(df))]

# > df
#         date  x1 x1_fit  x2 x2_fit x1_diff x2_diff
# 1 2019-11-04 100    150 110    170      50      60
# 2 2019-11-05 120    142 130    172      22      42
# 3 2019-11-06 111    146 151    176      35      25
# 4 2019-11-07 152    148 152    178      -4      26
# 5 2019-11-08 110    123 150    173      13      23
# 6 2019-11-09 112    120 142    170       8      28
# 7 2019-11-10 111    145 161    175      34      14

在基础 R 中,您可以使用在拟合列上循环遍历唯一列名称和差异

> lapply(setNames(nm = unique(gsub("_.*", "", names(df)))), function(nm) {
    fit <- paste0(nm, "_fit")
    diff <- df[, nm] - df[, fit]
})
# $x1
# [1] -50 -22 -35   4 -13  -8 -34
# 
# $x2
# [1] -60 -42 -25 -26 -23 -28 -14

在这里,我将日期列设置为行名称并使用删除列

df <- data.frame(date,x1,x1_fit,x2,x2_fit)
row.names(df) <- df$date
df$date <- NULL

但是您可以只循环遍历没有日期列的列名。

来自@mt1022 的解决方案很简单,但是由于您已将其标记为dplyr ,因此这是一种遵循它的方法,我们将数据转换为长格式,减去相应的值并再次以宽格式获取数据。

library(dplyr)
library(tidyr)

df %>%
  pivot_longer(cols = -date) %>%
  mutate(name = sub('_.*', '', name)) %>%
  group_by(date, name) %>%
  summarise(diff = diff(value)) %>%
  pivot_wider(names_from = name, values_from = diff) %>%
  rename_at(-1, ~paste0(., "_diff")) %>%
  left_join(df, by = "date")

#  date       x1_diff x2_diff    x1 x1_fit    x2 x2_fit
#  <date>       <dbl>   <dbl> <dbl>  <dbl> <dbl>  <dbl>
#1 2019-11-04      50      60   100    150   110    170
#2 2019-11-05      22      42   120    142   130    172
#3 2019-11-06      35      25   111    146   151    176
#4 2019-11-07      -4      26   152    148   152    178
#5 2019-11-08      13      23   110    123   150    173
#6 2019-11-09       8      28   112    120   142    170
#7 2019-11-10      34      14   111    145   161    175

我们也可以在base R进行split

out <- sapply(split.default(df[-1], sub("_.*", "", names(df)[-1])), 
         function(x) x[,2] - x[1])
df[sub("\\..*", "_diff", names(lst1))] <- out
df
#         date  x1 x1_fit  x2 x2_fit x1_diff x2_diff
#1 2019-11-04 100    150 110    170      50      60
#2 2019-11-05 120    142 130    172      22      42
#3 2019-11-06 111    146 151    176      35      25
#4 2019-11-07 152    148 152    178      -4      26
#5 2019-11-08 110    123 150    173      13      23
#6 2019-11-09 112    120 142    170       8      28
#7 2019-11-10 111    145 161    175      34      14

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM