Как использовать dplyr: mutate для многопараметрических пар столбцов, указанных частями имени переменной - PullRequest
0 голосов
/ 03 января 2019

У меня есть следующий пример:

df <- data.frame(
id = c(1,2,3),
  fix_01.2012 = c(2,5,7),
  fix_02.2012 = c(5,1,7),
  fix_03.2012 = c(6,1,5),
  fox_01.2012 = c(0.4, 0.5, 0.7),
  fox_02.2012 = c(0.6, 0.5, 0.8),
  fox_03.2012 = c(0.7, 0.5, 0.9)
  )

  id fix_01.2012 fix_02.2012 fix_03.2012 fox_01.2012 fox_02.2012 fox_03.2012
1  1           2           5           6         0.4         0.6         0.7
2  2           5           1           1         0.5         0.5         0.5
3  3           7           7           5         0.7         0.8         0.9

Таблица ниже - это то, что я хочу получить. Я хочу создать новый столбец для каждой даты (например, "01.2012"):

res_date = fix_date * fox_date

Поскольку у меня много дат / пар дат, я думаю, что это нужно сделать, просматривая имена.

 id fix_01.2012 fix_02.2012 fix_03.2012 fox_01.2012 fox_02.2012 fox_03.2012 res_01.2012 res_02.2012 res_03.2012
1  1           2           5           6         0.4         0.6         0.7         0.8         3.0         4.2
2  2           5           1           1         0.5         0.5         0.5         2.5         0.5         0.5
3  3           7           7           5         0.7         0.8         0.9         4.9         5.6         4.5

Кто-нибудь может помочь? Большое спасибо заранее!

Ответы [ 3 ]

0 голосов
/ 03 января 2019

Если вам нужен подход tidyverse, потребуется немного аккуратной оценки, чтобы получить то, что вы хотите.

library(tidyverse)

df <- data.frame(
  id = c(1,2,3),
  fix_01.2012 = c(2,5,7),
  fix_02.2012 = c(5,1,7),
  fix_03.2012 = c(6,1,5),
  fox_01.2012 = c(0.4, 0.5, 0.7),
  fox_02.2012 = c(0.6, 0.5, 0.8),
  fox_03.2012 = c(0.7, 0.5, 0.9)
)

# colnames with "fix" 
fix <- names(df)[grepl("fix",names(df))]

# colnames with "fox"
fox <- names(df)[grepl("fox",names(df))]

# Iterate over the two vectors of names and column bind the results (map2_dfc).  
# Since these are strings, we need to have them evaluated as symbols
# Creating the column name just requires the string to be evaluated.

map2_dfc(fix, fox, ~transmute(df, !!paste0("res", str_extract(.x, "_(0\\d)")) := !!sym(.x) * !!sym(.y)))

#>   res_01 res_02 res_03
#> 1    0.8    3.0    4.2
#> 2    2.5    0.5    0.5
#> 3    4.9    5.6    4.5
0 голосов
/ 03 января 2019

Гораздо более многословно, чем другие ответы, но, на мой взгляд, легче читать / редактировать / адаптировать, это подход с широким круговоротом (способ, которым я бы обосновал проблему, если бы решал ее шаг за шагом) :

library(tidyr)
library(dplyr)

df %>% 
  gather(-id, key=colname, value=value) %>% 
  separate(colname, c('fixfox', 'date'), sep='_') %>% 
  spread(key=fixfox, value=value) %>% 
  mutate(res=fix*fox) %>% 
  gather(-id, -date, key=colname, value=value) %>% 
  unite(new_colname, colname, date, sep='_') %>% 
  spread(key=new_colname, value=value)
0 голосов
/ 03 января 2019

Вот идея, которая использует split.default для разделения фрейма данных на основе похожих имен столбцов (в зависимости от ваших условий). Затем мы перебираем этот список и умножаем столбцы. В этом случае мы используем Reduce (а не i[1]*i[2]) для умножения, чтобы учесть более двух столбцов

do.call(cbind, 
   lapply(split.default(df[-1], gsub('.*_', '', names(df[-1]))), function(i) Reduce(`*`, i)))

#     01.2012 02.2012 03.2012
#[1,]     0.8     3.0     4.2
#[2,]     2.5     0.5     0.5
#[3,]     4.9     5.6     4.5

Свяжите их с оригиналом с помощью cbind.data.frame()

...