美文网首页Cook R数据科学与R语言玩转大数据
【r<-格式|方案】长宽格式互相转换

【r<-格式|方案】长宽格式互相转换

作者: 王诗翔 | 来源:发表于2017-10-18 11:15 被阅读50次

    问题

    你想要把数据从宽格式转换为长格式。

    R中许多函数希望输入的数据是长格式而不是宽格式。然而像SPSS软件经常使用宽格式数据。

    方案

    下面有两类方法:

    • tidyr包的gather()spread()函数。这是reshape2包的一个新接口。

    • reshape2包的melt()dcast()函数。

    这里不包含其他一些实现的方法,因为这些方法不是很好使用:

    • reshape()函数,它比较让人迷惑,因为它是R的基础包的一部分,而不是reshape2包的一部分。

    • stack()unstack()

    样例数据

    这里使用的数据框包含同样数据的长、宽格式。它们接下来会被相互转换。

    olddata_wide <- read.table(header=TRUE, text='
     subject sex control cond1 cond2
           1   M     7.9  12.3  10.7
           2   F     6.3  10.6  11.1
           3   F     9.5  13.1  13.8
           4   M    11.5  13.4  12.9
    ')
    # 确保subject列是一个因子
    olddata_wide$subject <- factor(olddata_wide$subject)
    
    olddata_long <- read.table(header=TRUE, text='
     subject sex condition measurement
           1   M   control         7.9
           1   M     cond1        12.3
           1   M     cond2        10.7
           2   F   control         6.3
           2   F     cond1        10.6
           2   F     cond2        11.1
           3   F   control         9.5
           3   F     cond1        13.1
           3   F     cond2        13.8
           4   M   control        11.5
           4   M     cond1        13.4
           4   M     cond2        12.9
    ')
    # 确保subject列是一个因子
    olddata_long$subject <- factor(olddata_long$subject)
    

    tidyr

    从宽格式到长格式

    使用 gather:

    olddata_wide
    #>   subject sex control cond1 cond2
    #> 1       1   M     7.9  12.3  10.7
    #> 2       2   F     6.3  10.6  11.1
    #> 3       3   F     9.5  13.1  13.8
    #> 4       4   M    11.5  13.4  12.9
    
    library(tidyr)
    
    # The arguments to gather():
    # - data: Data object
    # - key: Name of new key column (made from names of data columns)
    # - value: Name of new value column
    # - ...: Names of source columns that contain values
    # - factor_key: Treat the new key column as a factor (instead of character vector)
    data_long <- gather(olddata_wide, condition, measurement, control:cond2, factor_key=TRUE)
    data_long
    #>    subject sex condition measurement
    #> 1        1   M   control         7.9
    #> 2        2   F   control         6.3
    #> 3        3   F   control         9.5
    #> 4        4   M   control        11.5
    #> 5        1   M     cond1        12.3
    #> 6        2   F     cond1        10.6
    #> 7        3   F     cond1        13.1
    #> 8        4   M     cond1        13.4
    #> 9        1   M     cond2        10.7
    #> 10       2   F     cond2        11.1
    #> 11       3   F     cond2        13.8
    #> 12       4   M     cond2        12.9
    

    在这个例子中,来源列通过control:cond2指定聚集到一起。这里的意思是使用位置上在controlconda2之间(包括controlconda2)的所有列。另一种使用的方式是单独为每一列命名,如下:

    gather(olddata_wide, condition, measurement, control, cond1, cond2)
    

    如果你需要编程化使用gather()函数,可能需要使用包含列名的变量。想要实现它的话,你需要使用gather_()函数,它会使用字符串而不是没加引号的列名。

    keycol <- "condition"
    valuecol <- "measurement"
    gathercols <- c("control", "cond1", "cond2")
    
    gather_(olddata_wide, keycol, valuecol, gathercols)
    

    备择:重命名变量列的因子水平,并排序。

    # 重命名因子水平
    levels(data_long$condition)[levels(data_long$condition)=="cond1"] <- "first"
    levels(data_long$condition)[levels(data_long$condition)=="cond2"] <- "second"
    
    # 首先按照subject排序,然后按condition
    data_long <- data_long[order(data_long$subject, data_long$condition), ]
    data_long
    #>    subject sex condition measurement
    #> 1        1   M   control         7.9
    #> 5        1   M     first        12.3
    #> 9        1   M    second        10.7
    #> 2        2   F   control         6.3
    #> 6        2   F     first        10.6
    #> 10       2   F    second        11.1
    #> 3        3   F   control         9.5
    #> 7        3   F     first        13.1
    #> 11       3   F    second        13.8
    #> 4        4   M   control        11.5
    #> 8        4   M     first        13.4
    #> 12       4   M    second        12.9
    

    从长格式到宽格式

    使用 spread:

    olddata_long
    #>    subject sex condition measurement
    #> 1        1   M   control         7.9
    #> 2        1   M     cond1        12.3
    #> 3        1   M     cond2        10.7
    #> 4        2   F   control         6.3
    #> 5        2   F     cond1        10.6
    #> 6        2   F     cond2        11.1
    #> 7        3   F   control         9.5
    #> 8        3   F     cond1        13.1
    #> 9        3   F     cond2        13.8
    #> 10       4   M   control        11.5
    #> 11       4   M     cond1        13.4
    #> 12       4   M     cond2        12.9
    
    library(tidyr)
    
    # The arguments to spread():
    # - data: Data object
    # - key: Name of column containing the new column names
    # - value: Name of column containing values
    data_wide <- spread(olddata_long, condition, measurement)
    data_wide
    #>   subject sex cond1 cond2 control
    #> 1       1   M  12.3  10.7     7.9
    #> 2       2   F  10.6  11.1     6.3
    #> 3       3   F  13.1  13.8     9.5
    #> 4       4   M  13.4  12.9    11.5
    

    备择:一些可以使数据看起来更nice的操作。

    # 重命名
    names(data_wide)[names(data_wide)=="cond1"] <- "first"
    names(data_wide)[names(data_wide)=="cond2"] <- "second"
    
    # 排序
    data_wide <- data_wide[, c(1,2,5,3,4)]
    data_wide
    #>   subject sex control first second
    #> 1       1   M     7.9  12.3   10.7
    #> 2       2   F     6.3  10.6   11.1
    #> 3       3   F     9.5  13.1   13.8
    #> 4       4   M    11.5  13.4   12.9
    

    因子水平的顺序决定了列的顺序。水平次序能够在重塑之前被改变(changed),或者列也可以在之后重新排序(re-ordered)。

    reshape2

    从宽格式到长格式

    使用 melt:

    olddata_wide
    #>   subject sex control cond1 cond2
    #> 1       1   M     7.9  12.3  10.7
    #> 2       2   F     6.3  10.6  11.1
    #> 3       3   F     9.5  13.1  13.8
    #> 4       4   M    11.5  13.4  12.9
    
    library(reshape2)
    
    # 指定id.vars:需要保持的变量名
    melt(olddata_wide, id.vars=c("subject", "sex"))
    #>    subject sex variable value
    #> 1        1   M  control   7.9
    #> 2        2   F  control   6.3
    #> 3        3   F  control   9.5
    #> 4        4   M  control  11.5
    #> 5        1   M    cond1  12.3
    #> 6        2   F    cond1  10.6
    #> 7        3   F    cond1  13.1
    #> 8        4   M    cond1  13.4
    #> 9        1   M    cond2  10.7
    #> 10       2   F    cond2  11.1
    #> 11       3   F    cond2  13.8
    #> 12       4   M    cond2  12.9
    

    melt的一些选项可以使得输出更好处理:

    data_long <- melt(olddata_wide,
            # 变量ID,需要保持的变量名
        id.vars=c("subject", "sex"),
            # 来源列(被转换的)
        measure.vars=c("control", "cond1", "cond2" ),
            # 目的列的名字可以确定测量列数值的来自的原始列(变量)
            # 这里measurement是数值,condition指定了其来源
        variable.name="condition",
        value.name="measurement"
    )
    data_long
    #>    subject sex condition measurement
    #> 1        1   M   control         7.9
    #> 2        2   F   control         6.3
    #> 3        3   F   control         9.5
    #> 4        4   M   control        11.5
    #> 5        1   M     cond1        12.3
    #> 6        2   F     cond1        10.6
    #> 7        3   F     cond1        13.1
    #> 8        4   M     cond1        13.4
    #> 9        1   M     cond2        10.7
    #> 10       2   F     cond2        11.1
    #> 11       3   F     cond2        13.8
    #> 12       4   M     cond2        12.9
    

    如果你不设定measure.varsmelt函数会自动使用除id.vars的所有其他变量。反之亦然。

    如果你不指定variable.name,它会把那列命名为"variable",如果你不使用value.name变量,它会将它命名为"measurement"

    备择:重命名变量列的因子水平。

    # 重命名因子名
    levels(data_long$condition)[levels(data_long$condition)=="cond1"] <- "first"
    levels(data_long$condition)[levels(data_long$condition)=="cond2"] <- "second"
    
    # 首先按subject排序,然后按condition排序
    data_long <- data_long[ order(data_long$subject, data_long$condition), ]
    data_long
    #>    subject sex condition measurement
    #> 1        1   M   control         7.9
    #> 5        1   M     first        12.3
    #> 9        1   M    second        10.7
    #> 2        2   F   control         6.3
    #> 6        2   F     first        10.6
    #> 10       2   F    second        11.1
    #> 3        3   F   control         9.5
    #> 7        3   F     first        13.1
    #> 11       3   F    second        13.8
    #> 4        4   M   control        11.5
    #> 8        4   M     first        13.4
    #> 12       4   M    second        12.9
    

    从长格式到宽格式

    下面代码使用dcast函数重塑数据。这个函数用于数据框,如果你处理数组或矩阵,替换使用acast

    olddata_long
    #>    subject sex condition measurement
    #> 1        1   M   control         7.9
    #> 2        1   M     cond1        12.3
    #> 3        1   M     cond2        10.7
    #> 4        2   F   control         6.3
    #> 5        2   F     cond1        10.6
    #> 6        2   F     cond2        11.1
    #> 7        3   F   control         9.5
    #> 8        3   F     cond1        13.1
    #> 9        3   F     cond2        13.8
    #> 10       4   M   control        11.5
    #> 11       4   M     cond1        13.4
    #> 12       4   M     cond2        12.9
    
    # From the source:
    # "subject" and "sex" are columns we want to keep the same
    # "condition" is the column that contains the names of the new column to put things in
    # "measurement" holds the measurements
    # "subject" 和 "sex" 是我们想要保留的列
    # "condition"是我们想要放入新列名的列
    # "measurement"包含数值
    
    library(reshape2)
    
    data_wide <- dcast(olddata_long, subject + sex ~ condition, value.var="measurement")
    data_wide
    #>   subject sex cond1 cond2 control
    #> 1       1   M  12.3  10.7     7.9
    #> 2       2   F  10.6  11.1     6.3
    #> 3       3   F  13.1  13.8     9.5
    #> 4       4   M  13.4  12.9    11.5
    

    备择:一些可以使数据看起来更nice的操作。

    # 重命名
    names(data_wide)[names(data_wide)=="cond1"] <- "first"
    names(data_wide)[names(data_wide)=="cond2"] <- "second"
    
    # 重排序
    data_wide <- data_wide[, c(1,2,5,3,4)]
    data_wide
    #>   subject sex control first second
    #> 1       1   M     7.9  12.3   10.7
    #> 2       2   F     6.3  10.6   11.1
    #> 3       3   F     9.5  13.1   13.8
    #> 4       4   M    11.5  13.4   12.9
    

    因子水平的顺序决定了列的顺序。水平次序能够在重塑之前被改变(changed),或者列也可以在之后重新排序(re-ordered)。


    原文链接:http://www.cookbook-r.com/Manipulating_data/Converting_data_between_wide_and_long_format/

    相关文章

      网友评论

        本文标题:【r<-格式|方案】长宽格式互相转换

        本文链接:https://www.haomeiwen.com/subject/ngmsuxtx.html