изменить данные в столбце с предыдущей информацией в другом столбце - PullRequest
5 голосов
/ 07 апреля 2020

У меня есть набор данных с тремя столбцами. Столбец user имеет два действия, включая action1 и action2. action2 содержит информацию, только если столбец action1 содержит данные A. Я хочу объединить данные P в action1 с предыдущими данными в action2. Например, если action2 имеет ac, а в следующей строке P в action1, я хочу изменить P на Pac и продолжить (все P превращаются в Pac ) до action2 изменения. Обратите внимание, что этот процесс должен повторяться для каждого user.

df<-read.table(text="
user   action1    action2 
1        A          a
1        B          NA
1        P          NA
1        P          NA
1        A          ac
1        P          NA
2        B          NA
2        P          NA
2        A          aa
2        P          NA
2        AB         aa",header=T)

result: (I highlighted those rows that infected)
user   action1    action2 
1        A          a
1        B          NA
1        Pa         NA <-
1        Pa         NA <-
1        A          ac
1        Pac        NA <-
2        B          NA
2        P          NA
2        A          aa
2        Paa        NA <-
2        AB         NA

Спасибо

Ответы [ 3 ]

2 голосов
/ 07 апреля 2020
library('data.table')
library('zoo')
# Using zoo::na.locf(), fill NA with the previous value and group by user. Also `na.locf` will not remove NA.
setDT(df)[, V3 := na.locf(action2, na.rm = FALSE), by = .(user)]     
# combine action1 with V3 column if action1 is equal to 'P' and it is not NA.
df[action1 == 'P' & !(is.na(V3)), action1 := paste0(action1, V3)] 
df[, V3 := NULL] # remove V3 column
df
#    user action1 action2
# 1:    1       A       a
# 2:    1       B      NA
# 3:    1      Pa      NA
# 4:    1      Pa      NA
# 5:    1       A      ac
# 6:    1     Pac      NA
# 7:    2       B      NA
# 8:    2       P      NA
# 9:    2       A      aa
# 10:    2     Paa      NA
# 11:    2      AB      aa

Данные:

df<-read.table(text="
user   action1    action2 
               1        A          a
               1        B          NA
               1        P          NA
               1        P          NA
               1        A          ac
               1        P          NA
               2        B          NA
               2        P          NA
               2        A          aa
               2        P          NA
               2        AB         aa",header=T, stringsAsFactors = FALSE)
1 голос
/ 07 апреля 2020

Вот опция с добавлением tidyverse

library(dplyr)
library(tidyr)

# for each user carry valid action2 results forward 
df1 <- df %>% 
  group_by(user) %>% 
  tidyr::fill(action2) 

# replace missing values so they can be pasted
df1$action2 <- ifelse(is.na(df1$action2), "", df1$action2)

# add valid action2 results to action1 where action1 is "P"
df1$new <- ifelse(df1$action1 == "P",
                  paste0("P", df1$action2),
                  df1$action1)

# A tibble: 11 x 4
# Groups:   user [2]
    user action1 action2 new  
   <int> <chr>   <chr>   <chr>
 1     1 A       "a"     A    
 2     1 B       "a"     B    
 3     1 P       "a"     Pa   
 4     1 P       "a"     Pa   
 5     1 A       "ac"    A    
 6     1 P       "ac"    Pac  
 7     2 B       ""      B    
 8     2 P       ""      P    
 9     2 A       "aa"    A    
10     2 P       "aa"    Paa  
11     2 AB      "aa"    AB  

stringAsFactors = FALSE в считанные данные:

df<-read.table(text="
user   action1    action2 
1        A          a
1        B          NA
1        P          NA
1        P          NA
1        A          ac
1        P          NA
2        B          NA
2        P          NA
2        A          aa
2        P          NA
2        AB         aa",header=T, stringsAsFactors = FALSE)
0 голосов
/ 07 апреля 2020

Используйте fill() и unite() in tidyr:

library(dplyr)
library(tidyr)

df %>%
  mutate_if(is.factor, as.character) %>% 
  mutate(tmp = action2) %>%
  group_by(user) %>% 
  fill(tmp) %>%
  mutate(tmp = ifelse(action1 != "P", NA, tmp)) %>% 
  unite("action1", action1, tmp, sep = "", na.rm = TRUE)

# # A tibble: 11 x 3
# # Groups:   user [2]
#     user action1 action2
#    <int> <chr>   <chr>  
#  1     1 A       a      
#  2     1 B       NA     
#  3     1 Pa      NA     
#  4     1 Pa      NA     
#  5     1 A       ac     
#  6     1 Pac     NA     
#  7     2 B       NA     
#  8     2 P       NA     
#  9     2 A       aa     
# 10     2 Paa     NA     
# 11     2 AB      aa  
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...