重塑
这样做似乎有点低效;它似乎只是一个旋转/重塑操作,所以这是一个一次性的交易:
df2 <- reshape2::dcast(df, id + region ~ region, value.var = "region")
df2[,unique(df2$region)] <- lapply(df2[,unique(df2$region)], function(z) +!is.na(z))
df2
# id region Africa America Asia Europe
# 1 1 Asia 0 0 1 0
# 2 2 Africa 1 0 0 0
# 3 3 Europe 0 0 0 1
# 4 4 America 0 1 0 0
# 5 5 Asia 0 0 1 0
# 6 6 Africa 1 0 0 0
# 7 7 Europe 0 0 0 1
# 8 8 America 0 1 0 0
# 9 9 Asia 0 0 1 0
# 10 10 Africa 1 0 0 0
dcast 枢轴(同时保留原始"region" 列);中间值(在dcast 之后)是
reshape2::dcast(df, id+region~region, value.var="region")
# id region Africa America Asia Europe
# 1 1 Asia <NA> <NA> Asia <NA>
# 2 2 Africa Africa <NA> <NA> <NA>
# 3 3 Europe <NA> <NA> <NA> Europe
# 4 4 America <NA> America <NA> <NA>
# 5 5 Asia <NA> <NA> Asia <NA>
# 6 6 Africa Africa <NA> <NA> <NA>
# 7 7 Europe <NA> <NA> <NA> Europe
# 8 8 America <NA> America <NA> <NA>
# 9 9 Asia <NA> <NA> Asia <NA>
# 10 10 Africa Africa <NA> <NA> <NA>
所以我们需要做的就是将它们从字符串/NAs 转换为“是或不是NA”,这是使用+!is.na(z) 完成的。
基础 R,不重塑
uniqregion <- unique(df$region)
tmp <- +outer(df$region, unique(df$region), `==`)
colnames(tmp) <- uniqregion
tmp
# Asia Africa Europe America
# [1,] 1 0 0 0
# [2,] 0 1 0 0
# [3,] 0 0 1 0
# [4,] 0 0 0 1
# [5,] 1 0 0 0
# [6,] 0 1 0 0
# [7,] 0 0 1 0
# [8,] 0 0 0 1
# [9,] 1 0 0 0
# [10,] 0 1 0 0
cbind(df, tmp)
# id region Asia Africa Europe America
# 1 1 Asia 1 0 0 0
# 2 2 Africa 0 1 0 0
# 3 3 Europe 0 0 1 0
# 4 4 America 0 0 0 1
# 5 5 Asia 1 0 0 0
# 6 6 Africa 0 1 0 0
# 7 7 Europe 0 0 1 0
# 8 8 America 0 0 0 1
# 9 9 Asia 1 0 0 0
# 10 10 Africa 0 1 0 0
文字函数
如果你真的想要一个函数来循环它,我仍然推荐 lapply 而不是 for 循环:
binary <- function(data2, variable) {
uniq <- unique(data2[[variable]])
cbind(data2, as.data.frame(
lapply(setNames(nm = uniq),
function(z) +(z == data2[[variable]]) )
))
}
binary(df, "region")
# id region Asia Africa Europe America
# 1 1 Asia 1 0 0 0
# 2 2 Africa 0 1 0 0
# 3 3 Europe 0 0 1 0
# 4 4 America 0 0 0 1
# 5 5 Asia 1 0 0 0
# 6 6 Africa 0 1 0 0
# 7 7 Europe 0 0 1 0
# 8 8 America 0 0 0 1
# 9 9 Asia 1 0 0 0
# 10 10 Africa 0 1 0 0
(您可能会在此处考虑 不是 cbind(data2,,而只是返回 Asia:America 列,允许调用函数(用户)确定如何处理它;也许这太强迫症/泛化. 只是一个想法。)
使用for循环的文字函数
但如果你真的必须拥有它...
binary2 <- function(data2, variable) {
uniq <- unique(data2[[variable]])
for (nm in uniq) {
data2[[nm]] <- +(data2[[variable]] == nm)
}
data2
}
binary2(df, "region")
# id region Asia Africa Europe America
# 1 1 Asia 1 0 0 0
# 2 2 Africa 0 1 0 0
# 3 3 Europe 0 0 1 0
# 4 4 America 0 0 0 1
# 5 5 Asia 1 0 0 0
# 6 6 Africa 0 1 0 0
# 7 7 Europe 0 0 1 0
# 8 8 America 0 0 0 1
# 9 9 Asia 1 0 0 0
# 10 10 Africa 0 1 0 0