首页 > 解决方案 > 将“错过”数字的数据帧转换为“命中”数字的数据帧

问题描述

我有一个非常具体的疑问,但它应该很容易解决,我只是想不出如何......

我有一个像这样的简单数据框:

mydf <- data.frame(Shooter=1:3, Targets.missed=c(paste(sample(1:10,4),collapse=";"), paste(sample(1:10,5),collapse=";"), paste(sample(1:10,8),collapse=";")))
mydf
  Shooter   Targets.missed
1       1          3;8;4;7
2       2       10;1;5;7;4
3       3 5;9;4;10;8;1;6;7

这个数据框告诉我Targets每个Shooter.

我想获得一个不同的数据框,它告诉我 perTarget是哪个Shooter\s 做到的。

结果将是:

Target   hit.by.Shooters
1        1
2        1;2;3
3        2;3
4        NA
5        1
6        1;2
7        NA
8        2
9        1;2
10       1

标签: rdataframe

解决方案


我们通过将;“Targets.missed”拆分为“long”格式来扩展数据,然后按“Shooter”分组,summarise其中包含list从 1:10 开始不在“Targets.missed”列中unnest的数字,list按 'Target' 分组,将'Shooter' 元素放入单个字符串中,并使用1:10 填充缺失的summarise元素pasteuniqueNAcomplete

library(tidyverse)
mydf %>% 
   separate_rows(Targets.missed) %>% 
   group_by(Shooter) %>%
   summarise(Target = list(setdiff(1:10, Targets.missed))) %>% 
   unnest %>% 
   group_by(Target) %>%
   summarise(hit.by.Shooters = paste(unique(Shooter), collapse=";")) %>% 
   complete(Target = 1:10) 
# A tibble: 10 x 2
#   Target hit.by.Shooters
#    <int> <chr>          
# 1      1 1              
# 2      2 1;2;3          
# 3      3 2;3            
# 4      4 <NA>           
# 5      5 1              
# 6      6 1;2            
# 7      7 <NA>           
# 8      8 2              
# 9      9 1;2            
#10     10 1        

或者另一种选择是base R将'Targets.missed'(假设character类)拆分listvectors,循环遍历list,获取不在1:10(使用setdiff)中的值,list使用'Shooter'列设置名称, stackkey/vallist对成一个两列 data.frame,通过ing 由 'values' 分组的 'ind' 列获取unique行,从 1:10 获取完整的 'values' 数据集aggregatepastemerge

out <-  aggregate(ind ~ values, 
  unique(stack(setNames(lapply(strsplit(mydf$Targets.missed, ';'), 
    setdiff, x= 1:10), mydf$Shooter))), FUN = paste, collapse=";")
out1 <- merge(data.frame(values = 1:10), out, all.x = TRUE)

并在必要时更改列名

names(out1) <- c('Target', 'hit.by.Shooters')

数据

mydf <- structure(list(Shooter = 1:3, Targets.missed = c("3;8;4;7", "10;1;5;7;4", 
 "5;9;4;10;8;1;6;7")), class = "data.frame", row.names = c("1", 
 "2", "3"))

推荐阅读