условно заменить значения в предыдущих строках в R - PullRequest
0 голосов
/ 29 мая 2018

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

Это пример моих данных, которые в течение нескольких минут были потрачены на различные действия.

activity <- c("car","soccer","eat","drink")
category <- c("travel","sport","eat/drink","eat/drink")
duration <- c(75,15,10,160)
df <- data.frame(activity, category,duration)

   activity  category duration
1      car    travel       75
2   soccer     sport       15
3      eat eat/drink       10
4    drink eat/drink      160

Если в каком-либо ряду продолжительность «питья» составляет> 5 минут (как в строке 4), я хочу заменить «продолжительность» в этом ряду на 5 минут и добавить оставшееся время (в данном случае155 минут) до значения «длительности» в предыдущей строке, ЕСЛИ в предыдущей строке в качестве «категории» не указано «есть / пить», и в этом случае я хочу добавить оставшееся время к «продолжительности» строки перед предыдущей строкой.row ...

В приведенном выше примере я добавил бы 155 минут к "duration" в строке 2. Однако, если в строке 2 также есть "eat / drink" в качестве "категории", я бы хотелдобавьте 155 минут к предыдущему ряду (строка 1).

Спасибо за любую помощь!

До сих пор я пробовал:

df$duration[-nrow(df)] <- ifelse(df$activity[-1]=="drink" & df$duration[-1] > 5, 
                               df$duration + c(df$duration[-1]-5, 0),
                               df$duration)

, который добавляет 155 минут к предыдущему ряду и дает мне следующее:

    activity  category duration
1      car    travel       75
2   soccer     sport       15
3      eat eat/drink      165
4    drink eat/drink      160

и затем я просто заменил продолжительность в строке 4 на 5 минут, например:

df$duration <- ifelse(df$activity =="drink" & df$duration >5,
                      5,
                      df$duration)

, что дает мне это ...

   activity  category duration
1      car    travel       75
2   soccer     sport       15
3      eat eat/drink      165
4    drink eat/drink        5

Но я не могу понять, как переместить 155 минут в предыдущий ряд (ряд 2), при условии, что в качестве категории не указано «есть / пить».В этом случае я хочу переместить его в строку раньше и т. Д.

1 Ответ

0 голосов
/ 29 мая 2018

Вот ответ, но, к сожалению, мне не удалось создать нечеткое соединение, подразумевающее один столбец с левой стороны и два с правой стороны.Таким образом, в некоторый момент появляется декартово произведение (при слиянии).Ваш результат в 'df6', переменная 'duration2'.

activity <- c("car","soccer","eat","drink","car","drink","car","drink")
category <- c("travel","sport","eat/drink","eat/drink","travel","eat/drink","travel","eat/drink")
duration <- c(75,15,10,160,100,50,200,60)
df <- data.frame(activity, category,duration)

df$row<-1:nrow(df)

df1<-df[(activity=="drink")&(duration>5),]
df1$time<-df1$duration-5

library(dplyr)
df2<- df1
df2$row1<-lag(df2$row)
df2<-rename(df2,row2=row)

df$key <-1
df2$key <-1
df3 <- merge(df,df2,by="key") %>% filter(((is.na(row1)&(row<row2)|(row>row1)&(row<row2)))&(category.x!="eat/drink"))
df4 <- df3 %>% group_by(row1) %>% 
    summarize(row=last(row),time=last(time)) %>% select(row,time)
df5 <-      df %>% left_join(df4,by="row") %>% 
    mutate(duration2=ifelse(is.na(time),duration,duration+time)) %>%
    select(activity,category,duration,duration2,row)
df2 <- select(df2,row2,time)
df6 <- df5 %>% left_join(df2,by=c("row" = "row2")) %>% 
    mutate(duration2=ifelse(is.na(time),duration2,duration-time)) %>% 
    select(-time)
df6
#  activity  category duration duration2 row
#1      car    travel       75        75   1
#2   soccer     sport       15       170   2
#3      eat eat/drink       10        10   3
#4    drink eat/drink      160         5   4
#5      car    travel      100       145   5
#6    drink eat/drink       50         5   6
#7      car    travel      200       255   7
#8    drink eat/drink       60         5   8
...