将一个数据框映射到第二个数据框

时间:2018-12-27 12:23:36

标签: r grep dplyr gsub stringr

我有两个数据框,想同时映射两个数据框,并给出二进制值1(如果存在),否则为0。

第一DF

id       1_1   1_2   1_3   1_4   1_5   1_6   1_7   1_8   1_9   1_10  1_freq
111.txt  NA    NA    NA    NA    NA    NA    NA    NA    NA    NA    NA
112.txt  NA    NA    NA    NA    NA    NA    NA    NA    NA    NA    NA
113.txt  NA    NA    NA    NA    NA    NA    NA    NA    NA    NA    NA
114.txt  NA    NA    NA    NA    NA    NA    NA    NA    NA    NA    NA
115.txt  NA    NA    NA    NA    NA    NA    NA    NA    NA    NA    NA
116.txt  NA    NA    NA    NA    NA    NA    NA    NA    NA    NA    NA

第二个DF

id                 cats
111.cats           1,7,1
112.cats           1,1,2|1,3,2
113.cats           1,10,1|1,6,2
114.cats           1,4,2
115.cats           1,5,1
116.cats           1,1,2|1,8,1

在第二个DF$cats的第一行中有1,7,1,其中17合并并构成1_7列,并在该列上放置二进制值1剩下的列0被放置,最后1号进入1_freq列, 并且如果有任何行具有多个类似1,10,1|1,6,2的类别,其中1,10,1进入1_10列,1,6,2进入1_6列,并且这两个类别的频率总结并转到1_freq列。

DF应该看起来像这样

id       1_1   1_2   1_3   1_4   1_5   1_6   1_7   1_8   1_9   1_10  1_freq
111.txt  0     0     0     0     0     0     1     0     0     0     1
112.txt  1     0     1     0     0     0     0     0     0     0     4
113.txt  0     0     0     0     0     1     0     0     0     1     3
114.txt  0     0     0     1     0     0     0     0     0     0     2
115.txt  0     0     0     0     1     0     0     0     0     0     1
116.txt  1     0     0     0     0     0     0     1     0     0     3

希望问题很明确。 谢谢

2 个答案:

答案 0 :(得分:2)

这里是使用tidyverse的选项。我们通过在'cats'列的|处进行拆分来扩展数据集的行,然后通过在最后的separate处进行拆分,将{cats'划分为两列,并按'id ',获取“频率”列的,,提取“猫”末尾的数字,将其转换为sum,并指定factor,创建1s列( 'val'),levels设为“宽”格式

spread

现在,我们为初始数据集('df1')共有的列分配值

library(tidyverse)
o1 <- df2 %>% 
       separate_rows(cats, sep = "[|]") %>% 
       separate(cats, into = c('cats', 'freq'), 
           sep=",(?=[^,]+$)", convert = TRUE) %>%
       group_by(id) %>%
       mutate(freq = sum(freq), 
              cats = factor(str_extract(cats, "\\d+$"), levels = 1:10), 
              val = 1)  %>% 
       spread(cats, val, fill = 0) %>% 
       rename_at(-1, ~ paste0('1_', .))

数据

df1[is.na(df1)] <- 0
df1[names(o1)[-1]] <- o1[-1]
df1
#       id 1_1 1_2 1_3 1_4 1_5 1_6 1_7 1_8 1_9 1_10 1_freq
#1 111.txt   0   0   0   0   0   0   1   0   0    0      1
#2 112.txt   1   0   1   0   0   0   0   0   0    0      4
#3 113.txt   0   0   0   0   0   1   0   0   0    1      3
#4 114.txt   0   0   0   1   0   0   0   0   0    0      2
#5 115.txt   0   0   0   0   1   0   0   0   0    0      1
#6 116.txt   1   0   0   0   0   0   0   1   0    0      3

答案 1 :(得分:1)

尽管问题被标记为,但我很好奇的答案。

由于df1NA填充,除了id列和id列的不同之处仅在于结尾部分(txt与{{1 }})下面的答案建议完全根据cats中包含的数据来创建df1

df2
library(data.table)
library(magrittr)
long <- setDT(df2)[, strsplit(cats, "[|]"), by = id][
  , c(.(id = id), tstrsplit(V1, ","))][
    , V3 := factor(V3, levels = 1:10)]
df1 <- dcast(long, id ~ V3, function(x) pmax(1, length(x)), 
             value.var = "V3", drop = FALSE, fill = 0)[
               long[, sum(as.integer(V4)), by = id], on = "id", freq := V1][
                 , id := stringr::str_replace(id, "cats$", "txt")][
                   , setnames(.SD, names(.SD)[-1], paste0("1_", names(.SD)[-1]))]
df1

说明

在强制转换为data.table之后,通过将 id 1_1 1_2 1_3 1_4 1_5 1_6 1_7 1_8 1_9 1_10 1_freq 1: 111.txt 0 0 0 0 0 0 1 0 0 0 1 2: 112.txt 1 0 1 0 0 0 0 0 0 0 4 3: 113.txt 0 0 0 0 0 1 0 0 0 1 3 4: 114.txt 0 0 0 1 0 0 0 0 0 0 2 5: 115.txt 0 0 0 0 1 0 0 0 0 0 1 6: 116.txt 1 0 0 0 0 0 0 1 0 0 3 列拆分为“ |”,将df2从“字符串化”宽格式重塑为long形式。首先,然后将逗号分隔的部分分成catsV2的单独列。

然后,V4从字符转换为因数以保留列的顺序,当调用V3再次将其从长格式更改为宽格式时。由于OP要求显示至少存在一个组合的dcast(),因此此处必须使用自定义函数定义1而不是简单的function(x) pmax(1, length(x))。在更新联接中,频率之和被附加为列length。最后,在freq列中将“ cats”替换为“ txt”,并且列名(id列除外)的前缀为“ 1 _”。

数据

id