2016-12-20 1 views
1

Я хотел бы умножить несколько столбцов на фрейме данных на значения вектора (все значения в одном столбце должны быть умножены на одно и то же значение, которое будет разные по столбцу), сохраняя остальные столбцы такими, какие они есть.Продукт нескольких столбцов в кадре данных с помощью вектора с использованием dplyr

Поскольку я использую dplyr широко, я думал, что это может быть полезно использовать mutate_each функцию, так что я могу изменить все столбцы, в то же время, но я полностью потерял на синтаксисе на fun() части.

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

Это то, что я сделал до сих пор:

Представьте себе, что я хочу, чтобы умножить все столбцы в df но letters по weight_df вектора следующим образом:

df = data.frame(
    letters = c("A", "B", "C", "D"), 
    col1 = c(3, 3, 2, 3), 
    col2 = c(2, 2, 3, 1), 
    col3 = c(4, 1, 1, 3) 
) 
> df 
    letters col1 col2 col3 
1  A 3 2 4 
2  B 3 2 1 
3  C 2 3 1 
4  D 3 1 3 
> 
weight_df = c(1:3) 

Если я использую select перед нанесением mutate_each Я избавляюсь от столбцов letters (как и ожидалось), и это не то, что я хочу (часть из того факта, что вектор не применяется для каждого столбца, а для каждой строки), и я хочу наоборот):

df = df %>% 
    select(-letters) %>% 
    mutate_each(funs(. * weight_df)) 
> df 
    col1 col2 col3 
1 3 2 4 
2 6 4 2 
3 6 9 3 
4 3 1 3 

Но если я не выбрать какую-либо конкретную колонку, все значения в пределах letters удаляются (что делает много смысла, кстати), но это не то, что я хочу, ни (часть из факт, что вектор не применяется для каждого столбца, а для каждой строки! и я хочу наоборот):

df = df %>% 
    mutate_each(funs(. * issb_weight)) 
> df 
    letters col1 col2 col3 
1  NA 3 2 4 
2  NA 6 4 2 
3  NA 6 9 3 
4  NA 3 1 3 

(Пожалуйста, обратите внимание, что это очень простой dataframe и оригинальный один имеет путь больше строк и столбцов -Какой, к сожалению, не маркированные таким простым способом и шаблоны не могут быть получено)

+0

Я не думаю, что умножение делает то, что вы ожидаете. – James

+0

Возможно, вам захочется взглянуть на пакет purrr из той же семьи/авторов, что, я думаю, поможет вам «сопоставить» столбцы с соответствующими скалярами, которые вы умножаете. – Frank

+0

Нет, вы правы, пожалуйста, прочитайте последнюю заметку. – ccamara

ответ

2

Проблема здесь заключается в том, что вы в основном пытаются работать над рядами, а колонны, следовательно, такие методы, как mutate_* не будет работать. Если вас не устраивает много векторизованных подходов, предложенных в связанном вопросе, я думаю, используя tydeverse (и считая, что letters является уникальным идентификатором) одним из способов достижения этого является преобразование в длинную форму сначала, умножение одного столбца на группу, а затем конвертировать назад в широкий (не думаю, что это будет слишком эффективно)

library(tidyr) 
library(dplyr) 

df %>% 
    gather(variable, value, -letters) %>% 
    group_by(letters) %>% 
    mutate(value = value * weight_df) %>% 
    spread(variable, value) 

#Source: local data frame [4 x 4] 
#Groups: letters [4] 

#  letters col1 col2 col3 
# * <fctr> <dbl> <dbl> <dbl> 
# 1  A  3  4 12 
# 2  B  3  4  3 
# 3  C  2  6  3 
# 4  D  3  2  9 
2

попробовать этот

library(plyr) 
library(dplyr) 

df %>% select_if(is.numeric) %>% adply(., 1, function(x) x * weight_df) 
+0

, к какому пакету принадлежит 'adply()'? – mabdrabo

+0

не знал 'adply()' before. Для того, что я вижу, оно относится к 'plyr' – ccamara

+0

@manotheshark, оно отлично работает, за исключением того, что select удаляет столбцы (столбцы), которые не являются численными, и мне они нужны для других пользователей (хотя я не хочу выполнять операции с ним). – ccamara

2

использованием dplyr. Это фильтрует только числовые столбцы. Дает гибкость при выборе столбцов. Возвращает новые значения вместе со всеми остальными столбцами (нечисловых)

index <- which(sapply(df, is.numeric) == TRUE) 
df[,index] <- df[,index] %>% sweep(2, weight_df, FUN="*") 

> df 
    letters col1 col2 col3 
1  A 3 4 12 
2  B 3 4 3 
3  C 2 6 3 
4  D 3 2 9 
+0

Спасибо! Операции работают нормально, несмотря на то, что я получаю значения NA для столбца 'letters' – ccamara

+0

, почему это так? Я попробовал на данном образце и дал правильные значения 'letters' – mabdrabo

+0

Hum ... Думаю, я испортил свои' df' попытки других ответов. Повторяю все с нуля и отлично работает, хотя я должен признать, что это выглядит как черная магия, и я не понимаю, что делает ваш скрипт :( – ccamara

 Смежные вопросы

  • Нет связанных вопросов^_^