迭代R中的多维数据集

时间:2016-11-29 02:47:07

标签: r loops variables iteration apply

我吮吸循环并且[l,s,v]应用,我需要总结一个大的纵向数据集。我已经彻底搜索了我的问题好几天,我发布这个是因为我无法解决我的问题。

数据看起来像这样:

id var1_dose var1_unit var2_dose var2_unit var3_dose var3_unit
1         2        mL         5        mL         1        mL
2         4        mg         2        mg         4        mg
3         6       mcg         4       mcg         2       mcg
1         1        mL         1        mL         3        mL
2         3        mL         3        mL         5        mL

问题1

我希望使用apply或loop并输出var(1-3)剂量作为列表。

问题2

我想创建一个新变量,用剂量和单位连接数字,例如在第1行中,var1 = 2mL,var2 = 5mL,var3 = 1mL

非常感谢您的帮助。

4 个答案:

答案 0 :(得分:5)

这不是您要求的答案,但我认为这对您和其他人有帮助。请考虑tidying您的数据框。例如:

library(tidyr)

df1 <- data.frame(id = c(1,2,3,1,2),
       var1_dose = c(2,4,6,1,3),
       var1_unit = c("mL", "mg", "mcg", "mL", "mL"),
       var2_dose = c(5,2,4,1,3),
       var2_unit = c("mL", "mg", "mcg", "mL", "mL"),
       var3_dose = c(1,4,2,3,5),
       var3_unit = c("mL", "mg", "mcg", "mL", "mL"),
       stringsAsFactors = FALSE)

df1.gather <- gather(df1, variable, value, -id)
df1.tidy <- separate(df1.gather, variable,
            into = c("variable", "measurement"), sep = "_")

head(df1.tidy)

# id variable measurement value
# 1      var1        dose     2
# 2      var1        dose     4
# 3      var1        dose     6
# 1      var1        dose     1
# 2      var1        dose     3
# 1      var1        unit    mL
# 2      var1        unit    mg
# 3      var1        unit   mcg
# 1      var1        unit    mL
# 2      var1        unit    mL

# hacky workaround to get a units column
df1.tidy <- subset(df1.tidy, measurement != "unit")
df1.tidy$unit <- rep(c("mL", "mg", "mcg", "mL", "mL"), 3)

这种结构应该使得汇总,建模和绘图(使用ggplot2)变得更加容易。

答案 1 :(得分:2)

也许,这有助于

Weekly_Lecture CK(I_id, TS_name, WD_name)

答案 2 :(得分:1)

@akrun给出了正确的答案。如果您希望将结果作为列表 -

celery

答案 3 :(得分:0)

为了扩展我对@ neilfws答案的评论(并使用他的示例数据),您的数据最好以更长的形式进行整形,这将使您的分析的其余部分更加容易。但是,您的数据目前处于一种广泛的形式,因此您需要收集(融化)两组列,这比您的平均从长到长的重塑需要更多的工作。

一种选择是收集所有东西然后再扩散到广泛。这很好用,tidyr::spread非常特别关于索引的一个问题,因此您必须添加第二个ID列来标识结果的行,并且需要仔细考虑该列。

library(tidyverse)

df1_tidy <- df1 %>% 
    gather(var, val, -id) %>%    # gather everything to long form
    separate(var, c('var', 'var2')) %>%    # separate "var*" from dose/unit
    group_by(var2) %>% 
    mutate(var = parse_number(var),    # extract var to integer
           id2 = seq(n())) %>%    # add ID column for spreading
    spread(var2, val, convert = TRUE) %>% 
    select(-id2)    # cleanup

## # A tibble: 15 × 4
##       id   var  dose  unit
## *  <dbl> <dbl> <int> <chr>
## 1      1     1     2    mL
## 2      1     1     1    mL
## 3      1     2     5    mL
## 4      1     2     1    mL
## 5      1     3     1    mL
## 6      1     3     3    mL
## 7      2     1     4    mg
## 8      2     1     3    mL
## 9      2     2     2    mg
## 10     2     2     3    mL
## 11     2     3     4    mg
## 12     2     3     5    mL
## 13     3     1     6   mcg
## 14     3     2     4   mcg
## 15     3     3     2   mcg

或者,您可以单独设置gather。这种方法的问题在于它会为您提供您不想要的组合(var1和var3等),因此您必须filter返回原始文件。

df1_tidy <- df1 %>% 
    gather(var, dose, contains('dose')) %>% 
    gather(var_unit, unit, contains('unit')) %>% 
    mutate_at(vars(contains('var')), parse_number) %>%    # extract var numbers
    filter(var == var_unit) %>%    # filter to matching combinations
    select(-var_unit)    # cleanup

df1_tidy
##    id var dose unit
## 1   1   1    2   mL
## 2   2   1    4   mg
## 3   3   1    6  mcg
## 4   1   1    1   mL
## 5   2   1    3   mL
## 6   1   2    5   mL
## 7   2   2    2   mg
## 8   3   2    4  mcg
## 9   1   2    1   mL
## 10  2   2    3   mL
## 11  1   3    1   mL
## 12  2   3    4   mg
## 13  3   3    2  mcg
## 14  1   3    3   mL
## 15  2   3    5   mL

虽然tidyr没有(yet)具有多聚集功能,需要像上面这样的方法,data.table的melt版本允许您传递其measure.vars参数正则表达式模式,启用多聚集。语法看起来很不一样,有不同的东西要清理,但它会带你到同一个地方:

library(data.table)

dt1 <- melt(setDT(df1), 
            measure.vars = patterns('dose', 'unit'),    # set gathering patterns
            variable.factor = FALSE,    # because factor numbers are evil
            value.name = c('dose', 'unit'))    # set column names

dt1 <- dt1[, variable := as.integer(variable)][]    # cleanup

dt1
##     id variable dose unit
##  1:  1        1    2   mL
##  2:  2        1    4   mg
##  3:  3        1    6  mcg
##  4:  1        1    1   mL
##  5:  2        1    3   mL
##  6:  1        2    5   mL
##  7:  2        2    2   mg
##  8:  3        2    4  mcg
##  9:  1        2    1   mL
## 10:  2        2    3   mL
## 11:  1        3    1   mL
## 12:  2        3    4   mg
## 13:  3        3    2  mcg
## 14:  1        3    3   mL
## 15:  2        3    5   mL

无论您选择何种方法,一旦数据整洁,将doseunit结合起来很容易:

# base R
df1_tidy$dose_unit <- paste0(df1_tidy$dose, df1_tidy$unit)

# tidyverse
df1_tidy <- df1_tidy %>% mutate(dose_unit = paste0(dose, unit))

# data.table
dt1 <- dt1[, dose_unit := paste0(dose, unit)][]