我有两个数据框,想同时映射两个数据框,并给出二进制值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
,其中1
和7
合并并构成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
希望问题很明确。 谢谢
答案 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)
尽管问题被标记为dplyr,但我很好奇data.table的答案。
由于df1
用NA
填充,除了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
形式。首先,然后将逗号分隔的部分分成cats
至V2
的单独列。
然后,V4
从字符转换为因数以保留列的顺序,当调用V3
再次将其从长格式更改为宽格式时。由于OP要求显示至少存在一个组合的dcast()
,因此此处必须使用自定义函数定义1
而不是简单的function(x) pmax(1, length(x))
。在更新联接中,频率之和被附加为列length
。最后,在freq
列中将“ cats”替换为“ txt”,并且列名(id
列除外)的前缀为“ 1 _”。
id