我的问题有点像this,但数据结构的问题却有所不同:
示例数据:
df <-data.frame(id = c(1,2,3), stock_1 = c("Google","Microsoft","Yahoo"), stock_2 = c("Yahoo","Google","NA"))
我想转换成这个:
df <-data.frame(id = c(1,2,3), Google = c(1,1,0), Microsoft = c(0,1,0), Yahoo= c(1,0,1))
我尝试使用sapply()
,但从链接问题的答案来看,它只适用于一列。
答案 0 :(得分:5)
以下是使用data.table
:
library(data.table)
setDT(df)
dcast(melt(df, id = 'id')[value != 'NA'],
id ~ value, fun.aggregate = length)
# id Google Microsoft Yahoo
# 1: 1 1 0 1
# 2: 2 1 1 0
# 3: 3 0 0 1
fill = 0
是不必要的,为了容忍重复,我们可以尝试:
dcast(melt(df, id = 'id')[value != 'NA'],
id ~ value, fun.aggregate = function(x){ 1 * (length(x) != 0)})
2017年1月1日
正如Uwe所说,我们可以通过设置NA
从na.rm = TRUE
中删除它,如果它不是硬编码为字符串("NA"
),命令最终会看起来这样:
dcast(melt(df, id = 'id', na.rm = TRUE), id ~ value, fun.aggregate = length)
# or
dcast(melt(df, id = 'id', na.rm = TRUE),
id ~ value, fun.aggregate = function(x){ 1 * (length(x) != 0)})
答案 1 :(得分:2)
我们也可以使用tidyverse
library(tidyverse)
df %>%
gather(key, val, -id) %>%
filter(!is.na(val)) %>%
mutate(ind = 1) %>%
select(-key) %>%
spread(val, ind, fill = 0)
注意:最好使用NA
代替"NA"
,因为我们可以使用is.na
或na.omit
或complete.cases