编写一个重构数据的函数,以便每个ID只有一行使用数据表

时间:2016-02-24 21:41:33

标签: r data.table

我的问题建立在this问题的数据表答案的基础上(完全披露:我也提出了相关问题)。我也从其他SO问题和答案中受益匪浅,我花了很多时间阅读有关功能的内容,但还没有成功。

我有几行代码可以很好地用于我的目的,但我必须为5个不同的变量运行相同的代码。因此,我想编写一个函数来提高这个过程的效率。

示例数据框:

    id <- c(1, 1, 1, 1, 2, 3, 4, 4, 5, 5, 5)
    bmi <- c(18, 22, 23, 23, 20, 38, 30, 31, 21, 22, 24)
    other_data <- c("north_africa", "north_africa", "north_africa", "north_africa", "western_europe", "south_america", "eastern_europe", "eastern_europe", "ss_africa", "ss_africa", "ss_africa")
    other_data2 <- c(0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0)

    big_df <- data.frame(id, bmi, other_data, other_data2)


    #first make a data table with just the id and bmi columns
    bmi_dt <- as.data.table(big_df[c(1, 2)])

    #restructure data so that each ID only has one row
    bmi_dt <- bmi_dt[, c(bmi_new = paste(bmi, collapse = "; "), .SD), by = id][!duplicated(bmi_dt$id)]

    #split the strings of multiple numbers into 4 new cols
    bmi_dt[, c("bmi1", "bmi2", "bmi3", "bmi4") := tstrsplit(as.character(bmi_new), "; ", fixed=TRUE)]

    #make columns numeric
    bmi_dt <- bmi_dt[, lapply(.SD, as.numeric), by = id]

    #function to replace NA with 0 in a data table
    func_na <- function(DT) {
       for (i in names(DT))
          DT[is.na(get(i)), i:=0, with=FALSE]
    }

    func_na(bmi_dt)

最后一部分,这个功能,是由Matt Dowle在this SO回答中写的。

我一直试图通过从小开始为这个序列创建一个整体函数,但即使是最基本的部分也无法正常工作。这是我失败的尝试之一:

    big_func <- function(DT, old_col, id_col) {
      DT <- DT[, c(new_col = paste(old_col, collapse = "; "), .SD), by = id_col][!duplicated(id_col)]
      DT
    }  

    test <- big_func(bmi_dt, bmi, id)

我真的很想明白:

a)为什么我的尝试不适用于第一部分?

b)为所有这些创建一个大函数是否有意义?

c)如果是这样,我该怎么做?

修改:我现在看到有关重塑数据表here的问题。我认为我关于编写函数的问题是一个单独的问题。

1 个答案:

答案 0 :(得分:1)

您可以通过以下方式避免所有这些粘贴/拆分/转换/替换:

library(data.table)

big_dt <- as.data.table(big_df)
big_dt[, id_bmi := 1:.N, by = id]
dcast(big_dt[, list(id, id_bmi, bmi)], id ~ id_bmi, value.var = 'bmi', fill = 0)