2017-02-04 4 views
0

У меня есть два dataframes названного в качестве пользователя и MasterSubset данные после многократного состояния

User = read.csv(text = " 
Ticket,Vehicle,Created 
A,7164,1/1/2017 
B,7163,1/2/2017 
C,7162,26/1/2017", header = TRUE) 

Master = read.csv(text = " 
Ticket,Vehicle,Created 
E,7164,29/12/2016 
F,7163,26/12/2017 
G,7164,31/1/2017 
R,7164,02/02/2017 
H,7162,28/1/2017", header = TRUE) 

Я хочу, чтобы в User dataframe Я хотел бы добавить столбец Ticket для транспортных средств, которые соответствуют с номером транспортного средства для каждого i значения а также после созданной даты для значения i.

Ex: 
**Output** 

Ticket Vehicle Created  Ticket.1 Ticket.2  
A  7164 1/1/2017 G    R 
B  7163 1/2/2017 NA 
C  7162 26/1/2017 H 

Таким образом, для автомобиля 7164 две записи есть в Master, но только один после 1/1/2017, и что Г.

Я попытался следующий код

dfagg <- aggregate(Ticket ~ Vehicle + Created, Master, function(i) tail(i)) 
dfwide <- reshape(dfagg, timevar='Ticket', idvar=c('Vehicle'), direction="wide") 
names(dfwide) <- gsub("Vehicle", "Ticket", names(dfwide)) 

Однако я не получайте результат после даты создания транспортного средства, которая соответствует моему результату

+1

Пожалуйста, используйте инструменты для правильного форматирования фрагментов кода/данных. –

+0

Вы должны предоставить свои данные воспроизводимым образом. Посмотрите, как это сделать. Это облегчает помощь. – Rahul

ответ

2

NB: Я полагаю, что дата F - 26/12/2016 (не 26/1 2/2017), в противном случае ваш результат будет неправильным.

Одним из способов достижения этого является использование пакета sqldf.

Во-первых, конвертировать ваши даты от характера до даты:

User$Created = as.Date(User$Created, format = "%d/%m/%Y") 
Master$Created = as.Date(Master$Created, format = "%d/%m/%Y") 

Тогда присоединиться:

library(sqldf) 

Output <- sqldf("select u.Ticket, u.Vehicle, u.Created, 
         m.Ticket as Master_Ticket 
       from User u left join Master m 
        on (u.Vehicle = m.Vehicle and u.Created < m.Created)") 

Output 
# Ticket Vehicle Created Master_Ticket 
# 1  A 7164 2017-01-01    G 
# 2  A 7164 2017-01-01    R 
# 3  B 7163 2017-02-01   <NA> 
# 4  C 7162 2017-01-26    H 

EDIT: Если вы хотите иметь только одну строку для каждого пользователя билета, один путь следует заполнить:

Output2 <- sqldf("select u.Ticket, u.Vehicle, u.Created, 
         group_concat(m.Ticket, ' ') as Master_Tickets 
       from User u left join Master m 
        on (u.Vehicle = m.Vehicle and u.Created < m.Created) 
       group by u.Ticket, u.Vehicle, u.Created") 

Output2 
# Ticket Vehicle Created Master_Tickets 
# 1  A 7164 2017-01-01   G R 
# 2  B 7163 2017-02-01   <NA> 
# 3  C 7162 2017-01-26    H 

И если по какой-то причине вам абсолютно необходимо иметь один столбец для каждого матча:

library(dplyr) 
library(reshape2) 

Output3 = Output %>% 
    group_by(Ticket) %>% 
    mutate(column_name = paste0('Ticket.', row_number())) %>% 
    dcast(Ticket + Vehicle + Created ~ column_name, value.var = "Master_Ticket") 

Output3 
# Ticket Vehicle Created Ticket.1 Ticket.2 
# 1  A 7164 2017-01-01  G  R 
# 2  B 7163 2017-02-01  <NA>  <NA> 
# 3  C 7162 2017-01-26  H  <NA> 
+0

Если билет A имеет два совпадения, тогда создаются две строки, я хочу, чтобы ответы в двух отдельных столбцах были возможны. Ex Output # Ticket Vehicle Created Ticket.1 Ticket.2 # 1 A 7164 2017-01-01 GR # 2 B 7163 2017-02-01 # 3 C 7162 2017-01-26 H – Ashish

+0

@Ashish Хорошо, есть ли два совпадения max для каждой строки? – Scarabee

+0

@scrabee Может быть любое количество совпадений, 2 не является конкретным ответом. Он может иметь n совпадений. Спасибо – Ashish

1

A dplyr решение включая коррекцию данных для F отмеченное @Scarabee. lubridate используется для преобразования даты. dplyr::rename() может быть добавлен для получения более значимых имен столбцов.

library(lubridate) 
User = read.csv(text = " 
Ticket,Vehicle,Created 
A,7164,1/1/2017 
B,7163,1/2/2017 
C,7162,26/1/2017", header = TRUE, stringsAsFactors=FALSE) 
User$Created <- dmy(User$Created) 

Master = read.csv(text = " 
Ticket,Vehicle,Created 
E,7164,29/12/2016 
F,7163,26/12/2016 
G,7164,31/1/2017 
H,7162,28/1/2017", header = TRUE, stringsAsFactors=FALSE) 
Master$Created <- dmy(Master$Created) 

library(dplyr) 
User %>% 
    left_join(Master, by="Vehicle") %>% # left takes every row from Master 
    mutate(Ticket_y = ifelse(Created.x < Created.y, # apply date restriction 
          Ticket.y, NA)) %>% 
    group_by(Ticket.x) %>%   # group by User ticket  
    arrange(desc(Ticket.y)) %>%  # push NA values to end 
    filter(row_number() == 1) %>% # keep only first row withing group 
    ungroup() %>%     # remove grouping 
    select(Ticket.x, Created.x, Ticket_y) %>% # keep columns of interest 
    arrange(Ticket.x) # sort 

     Ticket.x Created.x Ticket_y 
     <chr>  <date> <chr> 
# 
# 1  A 2017-01-01  G 
# 2  B 2017-02-01  <NA> 
# 3  C 2017-01-26  H 
+1

Хороший ответ. FWIW Я думаю, что 'slice (1)' более компактен и, возможно, легче читать, чем 'filter (row_number() == 1)'. – Scarabee

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