如何折叠数据行

时间:2017-04-11 12:23:15

标签: r data.table

我是R和data.table的新手,但我正在尝试折叠采用以下格式的客户数据集 - 尽管它扩展到90列:

frame <- data.frame(
  customer_id = c(123, 123, 123),
  time = c(1, 2, 3),
  rec_type = c('contact', 'appointment', 'sale'),
  variable_1 = c('Yes', NA, "Yes"),
  variable_2 = c(NA, 'No', NA),
  variable_3 = c(NA, NA, 'complete'),
  variable_4 = NA, stringsAsFactors = FALSE)



customer_id     time    rec_type     variable_1     variable_2  variable_3 variable_4 
123             1        contact      Yes            NA          NA        NA
123             2        appointment  NA             No          NA        NA
123             3        sale         Yes             NA         complete    NA

之前我问过 - What's the best way to collapse sparse data into single rows in R? - 如何将每个客户的数据折叠成一行,并在data.table和dplyr中得到两个有用的答案。

但是,这些答案无法处理多个值,例如'rec_type'字段或者其值是同一个值variable_1的多个实例。

我想要提供一个跨列工作的函数,并返回一个行向量,其中每个字段是每个字段的单个值,如果所有列值都为空或者为“多个”,则为NA

在这种情况下:我的输出将是

customer_id     time     rec_type     variable_1     variable_2  variable_3 variable_4
    123         multiple multiple      Yes            No          complete    NA

我研究了如何计算各列的唯一值:

unique_values <- function(x){
  uniques <- dt[contact_no == x,][,lapply(.SD, uniqueN)]
  uniques
}

lapply(dt$contact_no, unique_values)

但无法使用如何使用uniques结果返回我想要的结果。

有人可以建议我可以使用的方法吗?

是否有更简单的方法来解决问题?

1 个答案:

答案 0 :(得分:3)

这是一个data.table方法。

setDT(frame)[, lapply(.SD, function(x)
                      {x <- unique(x[!is.na(x)])
                       if(length(x) == 1) as.character(x)
                       else if(length(x) == 0) NA_character_
                       else "multiple"}),
             by=customer_id]

我们的想法是使用lapply将匿名函数应用于所有变量,并以返回所需结果的方式构造函数。此函数去除NA值和重复,然后检查结果向量的长度。每个的输出都被转换为一个字符,以符合另一个customer_id发生“多重”的可能性。

返回

   customer_id     time rec_type variable_1 variable_2 variable_3 variable_4
1:         123 multiple multiple        Yes         No   complete         NA