2016-03-02 3 views
0

Я хочу вычитать значения из строки с меткой «базовая линия» из всех отмеченных иначе элементов в длинном формате данных. Это легко сделать в два этапа, используя left_join с подмножеством «базовая линия». Однако я не мог понять, как объединить vas_1 и vas_diff в одну цепочку.dplyr self-join with filter

library(dplyr) 
# Create test data 
n_users = 5 
vas = data_frame(
    user = rep(letters[1:n_users], each = 3), 
    group = rep(c("baseline", "early", "late"),n_users), 
    vas = round(rgamma(n_users*3, 10,1.4)) 
) 
# The above data are given 


# Assume some other operations are required 
vas_1 = vas %>% 
    mutate(
    vas = vas * 2 
) 
# I want to put the following into one 
# chain with the above 
# Use self-join to subtract baseline 
vas_diff = vas_1 %>% 
    filter(group != "baseline") %>% 
    # Problem is vas_1 here. Using . gives error here 
    # Adding copy = TRUE does not help 
# left_join(. %>% filter(group == "baseline") , by = c("user")) %>% 
    left_join(vas_1 %>% filter(group == "baseline") , by = c("user")) %>% 
    mutate(vas = vas.x - vas.y) %>% # compute offset 
    select(user, group.x, vas) # remove temporary variables 

vas_diff 
+0

Итак, какой желаемый результат? Ваш код работает. Вы просто пытаетесь упростить его или хотите получить другой результат? –

+0

Нет, результаты в порядке. Меня интересуют внутренние работы dplyr, особенно магия точки. И пытаясь понять сообщение об ошибке, запрашивающее копию, сбой даже с «копией» –

+1

Не совсем уверен, что я понимаю ваш вопрос, но проблема заключается в том, что вы отфильтровываете все наблюдения, где «группа ==» базовая линия », а затем, позже в трубе вы хотите снова получить доступ к этим строкам, но они больше не находятся в данных. Возможно, вам нужно что-то вроде 'vas_1%>% left_join (filter (., Group! =" Baseline "), filter (., Group ==" baseline "), by = c (" user "))'? –

ответ

1

Я использую анонимные функции, когда . следует использовать несколько раз:

... %>% (function(df) { ... }) %>% ... 

Таким образом, в вашем случае:

vas_diff = vas_1 %>% 
    filter(group != "baseline") %>% 
    (function(df) left_join(df, df %>% filter(group == "baseline") , by = c("user"))) %>% 
    mutate(vas = vas.x - vas.y) %>% # compute offset 
    select(user, group.x, vas) 

(который не будет производить желаемый результат, как описано в комментарии выше, но вы показываете, как использовать анонимную функцию)

но, возможно, вы захотите:

vas_diff = vas_1 %>% 
    left_join(
    x = filter(., group != "baseline") 
    , y = filter(., group == "baseline") 
    , by = c("user") 
) %>% 
    mutate(vas = vas.x - vas.y) %>% # compute offset 
    select(user, group.x, vas) # remove temporary variables