基于列名称中的模式的新列

时间:2014-04-16 23:36:49

标签: regex r grep data.table dplyr

我有一个数据表。我想创建一个新列,该列等于这些列中值的函数,列名称为

library(data.table)
library(dplyr)

set.seed(1)
DT <- data.table(Client = LETTERS[1:5], 
   Apple_2012 = rpois(5,5),  Apple_2013 = rpois(5,5), Pear_2012 = rpois(5,5), 
   Pear_2013 = rpois(5,5), Orange_2012 = rpois(5,5), Orange_2013 = rpois(5,5))

例如,我想

DT <- DT[ ,Fruit_2012 := Apple_2012 + Pear_2012 + Orange_2012]

但我想通过识别“2012”模式来做到这一点。像这样:

DT <- DT[ ,Fruit_2012 := sum(names(DT)[grep("2012", names(DT))]) ]

DT <- DT %.%
  mutate(Fruit_2012 = sum(names(DT)[grep("2012", names(DT))]) )

但这些方法都没有结果。

# Error in sum(names(DT)[grep("2012", names(DT))]) : 
#  invalid 'type' (character) of argument

我尝试过使用listquotewith=FALSE的组合,但没有更多运气。

3 个答案:

答案 0 :(得分:1)

set.seed(1)
df <- data.frame(
  Client = LETTERS[1:5], 
  Apple_2012 = rpois(5,5),
  Apple_2013 = rpois(5,5), 
  Pear_2012 = rpois(5,5), 
  Pear_2013 = rpois(5,5), 
  Orange_2012 = rpois(5,5), 
  Orange_2013 = rpois(5,5)
)

根据这些数据,我强烈建议您将其转换为tidy form,因为它放了 变量基础一致:

library(reshape2)

dfm <- melt(df, id = "Client")

variables <- colsplit(dfm$variable, "_", c("fruit", "year"))
dfm$variable <- NULL
dfm$fruit <- variables$fruit
dfm$year <- as.numeric(variables$year)

head(dfm)
#>   Client value fruit year
#> 1      A     4 Apple 2012
#> 2      B     4 Apple 2012
#> 3      C     5 Apple 2012
#> 4      D     8 Apple 2012
#> 5      E     3 Apple 2012
#> 6      A     8 Apple 2013

然后很容易用dplyr或其他方式概括你想要的方式:

library(dplyr)

dfm %.% group_by(Client, year) %.% summarise(fruit = mean(value))
#> Source: local data frame [10 x 3]
#> Groups: Client
#> 
#>    Client year fruit
#> 1       A 2012 5.333
#> 2       A 2013 5.667
#> 3       B 2012 3.333
#> 4       B 2013 5.333
#> 5       C 2012 5.667
#> 6       C 2013 7.000
#> 7       D 2012 5.000
#> 8       D 2013 6.000
#> 9       E 2012 4.667
#> 10      E 2013 4.333

答案 1 :(得分:1)

在这些情况下我经常使用Reduce

DT[, Fruit_2012 := Reduce('+', .SD), .SDcols = grep("2012", names(DT))]

#or
DT[, Fruit_2012_max := Reduce(pmax, .SD), .SDcols = grep("2012", names(DT))]

答案 2 :(得分:0)

尝试包含select函数。

 mutate(DT,fruits2012 = rowSums(DT %.% select(contains("2012"))))
这有点难看。但它的确有效。

我希望dplyr包中有.SD。若然,代码如下:

DT %.%
      select(contains("2012")) %.%
      mutate(fruits2012 = rowSums(.SD))