R - Получаване на стойности от други колони, когато са изпълнени условията

Имам таблица с данни нещо подобно.

Firm Year Moveyear Address OriginAddress DestinationAddress
  A  2000                     
  A  2001 2001              15Grand_Ave     700Grand_Ave
  A  2002
  A  2003 2003              700Grand_Ave    20Washington_Ave
  A  2004
  B  2000
  B  2001 
  B  2002 2002              2730State_st    40Washington_Ave
  B  2003
  B  2004
  C
  .
  .

Това е набор от панелни данни, показващ информация за преместване на всяка фирма за няколко години. Искам да добавя (или присвоя) адресна информация към колоната „Address“, като използвам колоните „OriginAddress“ и „DestinationAddress“.

Например 15Grand_Ave трябва да бъде присвоен към колоната с адрес на фирма A през 2000 г., тъй като това беше първоначалният адрес, преди фирмата да се премести на 700Grand_Ave през 2001 г. А 700Grand_Ave трябва да бъде присвоен към колоната с адрес на фирма A през 2001 г. и 2002 г., тъй като това беше нейният адрес преди него се премества на 20Washington_Ave през 2003 г.

Така че резултатът, който искам:

Firm Year Moveyear  Address        OriginAddress DestinationAddress
  A  2000         15Grand_Ave            
  A  2001 2001    700Grand_Ave      15Grand_Ave     700Grand_Ave
  A  2002         700Grand_Ave
  A  2003 2003    20Washington_Ave  700Grand_Ave    20Washington_Ave
  A  2004         20Washington_Ave
  B  2000         2730State_st
  B  2001         2730State_st
  B  2002 2002    40Washington_Ave  2730State_st    40Washington_Ave
  B  2003         40Washington_Ave
  B  2004         40Washington_Ave
  C
  .
  .

Предполагам, че трябва да използвам оператор for-loop и ifelse в R, но имам проблеми с кодирането. Моля, споделете всякакви идеи с мен.


person Chicago2017    schedule 07.06.2020    source източник
comment
Здравейте Chicago2017, моля, извикайте функцията dput на вашия data.frame/data.table и копирайте и поставете изхода от конзолата във вашия въпрос.   -  person hello_friend    schedule 07.06.2020


Отговори (2)


Ето един начин за използване на dplyr:

library(dplyr)

df %>%
  #Replace blanks with NA
  na_if('') %>%
  #Arrange data by Firm and Year 
  arrange(Firm, Year) %>%
  #Copy destination address to Address
  mutate(Address = DestinationAddress) %>%
  #For each Firm
  group_by(Firm) %>%
  #Fill NA values with previous non-NA values
  tidyr::fill(Address) %>%
  #Replace NA with first non-NA value in OriginAddress
  mutate(Address = replace(Address,is.na(Address),first(na.omit(OriginAddress))))


#  Firm   Year Moveyear Address          OriginAddress DestinationAddress
#   <chr> <int>    <int> <chr>            <chr>         <chr>             
# 1 A      2000       NA 15Grand_Ave      NA            NA                
# 2 A      2001     2001 700Grand_Ave     15Grand_Ave   700Grand_Ave      
# 3 A      2002       NA 700Grand_Ave     NA            NA                
# 4 A      2003     2003 20Washington_Ave 700Grand_Ave  20Washington_Ave  
# 5 A      2004       NA 20Washington_Ave NA            NA                
# 6 B      2000       NA 2730State_st     NA            NA                
# 7 B      2001       NA 2730State_st     NA            NA                
# 8 B      2002     2002 40Washington_Ave 2730State_st  40Washington_Ave  
# 9 B      2003       NA 40Washington_Ave NA            NA                
#10 B      2004       NA 40Washington_Ave NA            NA   

данни

df <- structure(list(Firm = c("A", "A", "A", "A", "A", "B", "B", "B", 
"B", "B"), Year = c(2000L, 2001L, 2002L, 2003L, 2004L, 2000L, 
2001L, 2002L, 2003L, 2004L), Moveyear = c(NA, 2001L, NA, 2003L, 
NA, NA, NA, 2002L, NA, NA), Address = c(NA, NA, NA, NA, NA, NA, 
NA, NA, NA, NA), OriginAddress = c("", "15Grand_Ave", "", "700Grand_Ave", 
"", "", "", "2730State_st", "", ""), DestinationAddress = c("", 
"700Grand_Ave", "", "20Washington_Ave", "", "", "", "40Washington_Ave", 
"", "")), class = "data.frame", row.names = c(NA, -10L))             
person Ronak Shah    schedule 07.06.2020
comment
Благодаря ви много за бързия отговор, Ronak! Това не е за вярване! Освен това ще гласувам веднага щом приложа тези кодове към моя. Все още не съм приложил тези кодове към моя набор от данни, но мисля, че определено ще работи за моя набор от данни (Ако не, ще оставя коментар тук). Още веднъж, много ви благодаря! - person Chicago2017; 07.06.2020

Базов R разтвор:

# Replace empty strings with NA_character: df_clean => data.frame
df_clean <- replace(df, df == "", NA_character_)

# Split apply combine NA filling function per firm: data.frame => stdout (console)
data.frame(do.call("rbind", lapply(split(df_clean, df_clean$Firm), function(x){
  x <- x[order(x$Year),]
  x$Address[1] <- ifelse(is.na(x$Address[1]), 
  x$OriginAddress[which(!(is.na(x$OriginAddress)))[1]],
                         x$Address[1])
  x$Address[which(is.na(x$Address))] <- x$DestinationAddress[which(is.na(x$Address))]
  x$Address <- na.omit(x$Address)[cumsum(!(is.na(x$Address)))]
  return(x)
    }
  )
), row.names = NULL)

Използване на данни, благодарение на @Ronak Shah:

df <- structure(list(Firm = c("A", "A", "A", "A", "A", "B", "B", "B", 
"B", "B"), Year = c(2000L, 2001L, 2002L, 2003L, 2004L, 2000L, 
2001L, 2002L, 2003L, 2004L), Moveyear = c(NA, 2001L, NA, 2003L, 
NA, NA, NA, 2002L, NA, NA), Address = c(NA, NA, NA, NA, NA, NA, 
NA, NA, NA, NA), OriginAddress = c("", "15Grand_Ave", "", "700Grand_Ave", 
"", "", "", "2730State_st", "", ""), DestinationAddress = c("", 
"700Grand_Ave", "", "20Washington_Ave", "", "", "", "40Washington_Ave", 
"", "")), class = "data.frame", row.names = c(NA, -10L))     
person hello_friend    schedule 07.06.2020