有没有一种简单的方法可以比较列表中数据框的匹配元素并将其替换为数据框?

时间:2020-03-27 20:07:28

标签: r

我有以下不同观察结果的数据框:

    df <- data.frame('Time' = c(1058,672,1153,1321,1408), 'Event' = c('LU6/LU12','LU48','LU12','LU6/LU12','LU6'), 'Name' = NA)

还有这个参考列表,其中每个向量的第一个元素是时间,其余的是完成的事件:

ReferenceList <- list('A' = c('500','LU24','LU12','LU6'),
                      'B' = c('1000','LU48','LU24','LU12','LU6'),
                      'C' = c('1500','LU48','LU24','LU12','LU6'))

考虑到观察到的时间与参考之间的最小差异,以及事件从列表中出现在哪个矢量中,我想用名称列的NA值替换列表中每个矢量的名称。对于这种情况,我将获得以下数据帧:

Time    Event     Name
1058    LU6/LU12  B
672     LU48      B
1153    LU12      B
1321    LU6/LU12  C
1408    Lu6       C

是否有R函数可以做到这一点或避免for循环的直接方法?

谢谢!

1 个答案:

答案 0 :(得分:0)

使用dplyrtidyr试试看似复杂的方法。

library(dplyr)
library(tidyr)

首先,我认为您当前存储的ReferenceList是一个坏主意。最好将数字存储为数字。

ref2 <- stack(ReferenceList) %>%
  transmute(Name = as.character(ind), values) %>%
  group_by(Name) %>%
  summarize(
    Time2 = as.integer(grep("^\\d+$", values, value = TRUE)),
    Event = list(grep("\\D", values, value = TRUE))
  ) %>%
  unnest(Event)
ref2
# # A tibble: 11 x 3
#    Name  Time2 Event
#    <chr> <int> <chr>
#  1 A       500 LU24 
#  2 A       500 LU12 
#  3 A       500 LU6  
#  4 B      1000 LU48 
#  5 B      1000 LU24 
#  6 B      1000 LU12 
#  7 B      1000 LU6  
#  8 C      1500 LU48 
#  9 C      1500 LU24 
# 10 C      1500 LU12 
# 11 C      1500 LU6  

这种格式(IMHO)更有用,以后可以很好地合并。

从这里

df %>%
  select(-Name) %>%
  mutate(
    rn = row_number(),
    Event = as.character(Event),
    Event_list = strsplit(Event, "/")
  ) %>%
  unnest(Event_list) %>%
  left_join(ref2, by = c("Event_list" = "Event")) %>%
  group_by(rn) %>%
  slice(which.min(abs(Time - Time2))) %>%
  select(Time, Event, Name) %>%
  ungroup()
# Adding missing grouping variables: `rn`
# # A tibble: 5 x 4
#      rn  Time Event    Name 
#   <int> <dbl> <chr>    <chr>
# 1     1  1058 LU6/LU12 B    
# 2     2   672 LU48     B    
# 3     3  1153 LU12     B    
# 4     4  1321 LU6/LU12 C    
# 5     5  1408 LU6      C