Создание нескольких новых столбцов во фрейме данных с использованием одной и той же функции - PullRequest
0 голосов
/ 30 октября 2019

Простите за основной вопрос. Я просто борюсь с чем-то, что должно быть простым. Скажем, у меня есть фрейм данных «Тест», в котором изначально есть три поля: Col1, Col2, Col3.

Я хочу создать новые столбцы на основе каждого из исходных столбцов. Значения в каждой строке новых столбцов будут указывать, будет ли соответствующее значение в соответствующей строке исходного столбца выше или ниже медианы исходного столбца. Так, например, в прикрепленном изображении Col4 основан на Col1. Col5 основан на Col2. Col6 на основе Col3.

пример тестового фрейма данных:

test dataframe example

Довольно просто выполнить эту функцию для одного столбца и вывести один столбец:

Test <- Test %>% mutate(Col4 = derivedFactor(

"below"= Col1 > median(Test$Col1),

"at"= Col1 == median(Test$Col1),

"above"= Col1 < median(Test$Col1)

.default = NA)

)

Но если я выполняю эту же операцию над 50 столбцами, запись / копирование-вставка и редактирование кода могут быть утомительными и неэффективными. Я должен упомянуть, что я надеюсь добавить новые столбцы в фрейм данных, а не создавать другой фрейм данных. Кроме того, во фрейме данных есть около 200 других полей, для которых эта функция не будет выполняться (поэтому я не могу просто использовать mutate_all). И столбцы не имеют одинакового имени (мои примеры выше - это просто примеры, а не фактический набор данных), поэтому я не могу найти шаблон для mutate_at. Может быть, есть способ передать список имен столбцов в команду mutate вручную?

Должен быть простой и элегантный способ сделать это. Если бы кто-то мог помочь, это было бы удивительно.

1 Ответ

0 голосов
/ 30 октября 2019

Вы можете сделать следующее, используя data.table.

Во-первых, я определяю функцию, которая применяется к числовому вектору, посредством чего она выводит соответствующую позицию элементов по отношению к медиане вектора:

med_fn = function(x){

  med = median(x)
  unlist(sapply(x, function(x){
    if(x > med) {'Above'} 
    else if(x < med) {'Below'}
    else {'At'}
  }))

}

> med_fn(c(1,2,3))
[1] "Below" "At"    "Above"

Давайте рассмотрим некоторые примеры данных:

dt = data.table(
  C1 = c(1, 2, 3),
  C2 = c(2, 1, 3),
  C3 = c(3, 2, 1)
)

old = c('C1', 'C2', 'C3') # Name of columns I want to perform operation on
new = paste0(old, '_medfn') # Name of new columns following operation

Используя аргументы .SD и .SDcols из data.table, я применяю med_fn к столбцам old,в моем случае столбцы C1, C2 и C3. Я называю новые столбцы C#_medfn:

dt[, (new) := lapply(.SD, med_fn), .SDcols = old]

Результат:

> dt
   C1 C2 C3 C1_medfn C2_medfn C3_medfn
1:  1  2  3    Below       At    Above
2:  2  1  2       At    Below       At
3:  3  3  1    Above    Above    Below
...