本文概述
本文带你了解为什么要将数据从长格式转换为宽格式,反之亦然,并探索如何使用melt()和dcast()在R中实现这一点
有时候人们需要将长格式的数据(你称其为”长格式”, 以后会清楚说明)转换为宽格式, 反之亦然。现实生活中的数据有各种各样的格式, 但是大多数R函数都是为一种特定形式设计的。
例如, 对于长格式, 将设计用于混合线性建模的lme4 :: lmer(), 用于可视化的ggplot2 :: ggplot()。但是还有其他针对宽格式设计的函数, 例如mosaicplot()。这意味着你需要转换表格以进行分析或可视化, 除非已经处理过数据且格式正确。
R中有几种用于格式转换的选项, 但是当你刚入门时, 它会变得非常混乱。
本教程将向你展示如何理解在长格式和宽格式之间转换数据的机制。你将探索以下主题:
- 你将了解有关长格式的更多信息。
- 然后, 你将了解广泛的形式。
- 你将回顾长格式和宽格式之间的差异;
- 之后, 你将看到从一种形式转换到另一种形式需要采取的步骤。
- 最后, 你将在R的帮助下实现所有这些功能。你将学习如何使用melt()和dcast()函数将长格式转换为宽格式。
数据
名称 | 性别 | 年2011 | 年2012 | 年2013 | 年2014 | 年2015 |
---|---|---|---|---|---|---|
杰克逊·史密斯 | 中号 | 74.69 | 84.99 | 91.73 | 105.11 | 111.04 |
索菲亚·约翰逊(Sophia Johnson) | F | NA | NA | NA | NA | 75.89 |
艾玛·威廉姆斯(Emma Williams) | F | NA | NA | 75.74 | 86.50 | 91.50 |
艾登·琼斯(Aiden Jones) | 中号 | NA | NA | NA | 71.89 | 81.42 |
利亚姆·布朗 | 中号 | 88.24 | 96.91 | 101.85 | 108.13 | 112.45 |
卢卡斯·戴维斯(Lucas Davis) | 中号 | 70.60 | 83.78 | 94.17 | 100.03 | 106.35 |
奥利维亚·米勒(Olivia Miller) | F | 64.78 | 80.76 | 87.30 | 97.13 | 103.80 |
艾娃·威尔逊(Ava Wilson) | F | 88.77 | 96.45 | 104.72 | 112.84 | NA |
该表显示了一个小地方的婴儿身高。身高是从2011年到2015年的测量值。你可能已经知道, NA表示”不可用”。从NA的位置, 你可以算出婴儿的年龄, 但婴儿的确切年龄却不高可从表中获得。这张表看起来井井有条, 但是对于任何想研究婴儿成长的人来说, 都有一个问题:重要的信息不是测量婴儿的绝对时间, 而是测量婴儿的年龄。你可以将此信息插入表格吗?在下面, 你可以看到一种方法:
名称 | 性别 | 年龄0 | 1岁 | AGE2岁 | 3岁 | 4岁 | 5岁 | 6岁 |
---|---|---|---|---|---|---|---|---|
杰克逊·史密斯 | 中号 | NA | 76.69 | 84.91 | 97.06 | 105.73 | 107.32 | NA |
索菲亚·约翰逊(Sophia Johnson) | F | NA | 76.05 | NA | NA | NA | NA | NA |
艾玛·威廉姆斯(Emma Williams) | F | 72.65 | 82.46 | 91.76 | NA | NA | NA | NA |
艾登·琼斯(Aiden Jones) | 中号 | 69.76 | 79.89 | NA | NA | NA | NA | NA |
利亚姆·布朗 | 中号 | NA | NA | 85.34 | 93.22 | 105.78 | 105.84 | 114.82 |
卢卡斯·戴维斯(Lucas Davis) | 中号 | 71.59 | 84.87 | 92.10 | 100.73 | 104.21 | NA | NA |
奥利维亚·米勒(Olivia Miller) | F | 62.74 | 81.39 | 92.02 | 98.32 | 106.44 | NA | NA |
艾娃·威尔逊(Ava Wilson) | F | NA | NA | 88.39 | 100.67 | 107.58 | 111.52 | NA |
NA的数量有所增加。 ##宽格式数据但是, 如果你想传达一个婴儿多少个月的时间, 该怎么办?就像这样:
名称 | 性别 | m4 | m6 | m7 | 10米 | m12 | … | m55 | m60 | m65 | m72 |
---|---|---|---|---|---|---|---|---|---|---|---|
杰克逊·史密斯 | 中号 | NA | NA | NA | NA | 76.69 | … | NA | 107.32 | NA | NA |
索菲亚·约翰逊(Sophia Johnson) | F | NA | NA | NA | NA | 76.05 | … | NA | NA | NA | NA |
艾玛·威廉姆斯(Emma Williams) | F | NA | NA | NA | 72.65 | NA | … | NA | NA | NA | NA |
艾登·琼斯(Aiden Jones) | 中号 | NA | 69.76 | NA | NA | NA | … | NA | NA | NA | NA |
利亚姆·布朗 | 中号 | NA | NA | NA | NA | NA | … | NA | 105.84 | NA | 114.82 |
卢卡斯·戴维斯(Lucas Davis) | 中号 | NA | NA | 71.59 | NA | NA | … | 104.21 | NA | NA | NA |
奥利维亚·米勒(Olivia Miller) | F | 62.74 | NA | NA | NA | NA | … | NA | NA | NA | NA |
艾娃·威尔逊(Ava Wilson) | F | NA | NA | NA | NA | NA | … | NA | NA | 111.52 | NA |
上表中有大量的NA。如果婴儿的相对测量时间不同, 那么宽的形式会浪费很多空间。另一种选择是包括2015年的婴儿年龄, 但这只有在绝对测量时间都相同的情况下才可能。如果婴儿的测量时间相差数月, 而你想知道以月为单位的年龄, 则该方法无效。那么这个例子似乎是唯一的方法。在这种情况下, 你可以考虑使用长格式。 ##长格式数据一位婴儿的所有测量结果均以宽格式显示在一行中, 而你只会看到一位婴儿的所有测量值以长格式显示。获取后者的最简单方法是在一行中显示孩子的名字, 测量时间和测量值(身高)。这正是该表显示的内容:
名称 | 性别 | 月 | 高度 |
---|---|---|---|
奥利维亚·米勒(Olivia Miller) | F | 4 | 62.74 |
艾登·琼斯(Aiden Jones) | 中号 | 6 | 69.76 |
卢卡斯·戴维斯(Lucas Davis) | 中号 | 7 | 71.59 |
艾玛·威廉姆斯(Emma Williams) | F | 10 | 72.65 |
杰克逊·史密斯 | 中号 | 12 | 76.69 |
… | … | … | … |
利亚姆·布朗 | 中号 | 72 | 114.82 |
如果按名称对数据进行排序, 则会得到类似下表所示的内容。显然, 该表比上面的表3占用的空间要小!
名称 | 性别 | 月 | 高度 |
---|---|---|---|
杰克逊·史密斯 | 中号 | 12 | 76.69 |
杰克逊·史密斯 | 中号 | 24 | 84.91 |
杰克逊·史密斯 | 中号 | 36 | 97.06 |
杰克逊·史密斯 | 中号 | 48 | 105.73 |
杰克逊·史密斯 | 中号 | 60 | 107.32 |
索菲亚·约翰逊(Sophia Johnson) | F | 12 | 76.05 |
艾玛·威廉姆斯(Emma Williams) | F | 10 | 72.65 |
… | … | … | … |
艾娃·威尔逊(Ava Wilson) | F | 65 | 111.52 |
长与宽
再次注意宽格式和长格式之间的根本区别:一个简单的区别是, 宽格式在一行中显示了一个人的许多测量结果, 而列名显示了这些测量结果。
下表连续显示了利亚姆·布朗(Liam Brown)在2011-2015年的身高:
名称 | 性别 | 年2011 | 年2012 | 年2013 | 年2014 | 年2015 |
---|---|---|---|---|---|---|
利亚姆·布朗 | 中号 | 88.24 | 96.91 | 101.85 | 108.13 | 112.45 |
在长形Liam Brown的身高中, 一栏显示:
名称 | 性别 | + |
---|---|---|
利亚姆·布朗 | 中号 | 85.34 |
利亚姆·布朗 | 中号 | 93.22 |
利亚姆·布朗 | 中号 | 105.78 |
利亚姆·布朗 | 中号 | 105.84 |
利亚姆·布朗 | 中号 | 114.82 |
如你所见, 你不知道什么是测量值。如果记下列名称, 则看起来像这样:
名称 | 性别 | 年2011, 2012, 2013, 2014, 2015 |
---|---|---|
利亚姆·布朗 | 中号 | 85.34 |
利亚姆·布朗 | 中号 | 93.22 |
利亚姆·布朗 | 中号 | 105.78 |
利亚姆·布朗 | 中号 | 105.84 |
利亚姆·布朗 | 中号 | 114.82 |
但是, 这有它自己的问题。索菲亚·约翰逊(Sophia Johnson)的身高未在2011-2014年进行测量。因此, 如你在下面看到的, 无法轻松设置列名:
名称 | 性别 | ? |
---|---|---|
利亚姆·布朗 | 中号 | 85.34 |
利亚姆·布朗 | 中号 | 93.22 |
利亚姆·布朗 | 中号 | 105.78 |
利亚姆·布朗 | 中号 | 105.84 |
利亚姆·布朗 | 中号 | 114.82 |
索菲亚·约翰逊(Sophia Johnson) | F | 76.05 |
从宽格式到长格式
可以将宽格式转换为长格式是逐步的过程。在将一行中的度量转换为一列之前, 你可以使表的制作方式使其每行中仅包含一个度量。让我们对此表进行操作:
名称 | 性别 | 年龄0 | 1岁 | AGE2岁 | 3岁 | 4岁 | 5岁 | 6岁 |
---|---|---|---|---|---|---|---|---|
艾玛·威廉姆斯(Emma Williams) | F | 72.65 | 82.46 | 91.76 | NA | NA | NA | NA |
艾登·琼斯(Aiden Jones) | 中号 | 69.76 | 79.89 | NA | NA | NA | NA | NA |
结果如下表所示:
名称 | 性别 | 年龄0 | 1岁 | AGE2岁 | 3岁 | 4岁 | 5岁 | 6岁 |
---|---|---|---|---|---|---|---|---|
艾玛·威廉姆斯(Emma Williams) | F | 72.65 | NA | NA | NA | NA | ||
艾玛·威廉姆斯(Emma Williams) | F | 82.46 | NA | |||||
艾玛·威廉姆斯(Emma Williams) | F | 91.76 | ||||||
艾登·琼斯(Aiden Jones) | 中号 | 69.76 | NA | NA | NA | NA | NA | |
艾登·琼斯(Aiden Jones) | 中号 | 79.89 |
在将分散在各列中的度量收集到一列之前, 你需要再创建一列以说明度量是什么, 如下所示:
名称 | 性别 | 测量 | 年龄0 | 1岁 | AGE2岁 | 3岁 | 4岁 | 5岁 | 6岁 |
---|---|---|---|---|---|---|---|---|---|
艾玛·威廉姆斯(Emma Williams) | F | 年龄0 | 72.65 | NA | NA | NA | NA | ||
艾玛·威廉姆斯(Emma Williams) | F | 1岁 | 82.46 | NA | |||||
艾玛·威廉姆斯(Emma Williams) | F | AGE2岁 | 91.76 | ||||||
艾登·琼斯(Aiden Jones) | 中号 | 年龄0 | 69.76 | NA | NA | NA | NA | NA | |
艾登·琼斯(Aiden Jones) | 中号 | 1岁 | 79.89 |
列名称通常是”度量”或”键”。你可以在上表中注意到, 列名和一列中分别有” age0″, ” age1″, ” age2″, ” age3″, ” age4″, ” age5″。如果省略列名, 则表如下所示。
名称 | 性别 | 测量 | + | __ | ___ | ____ | _____ | ______ | _______ |
---|---|---|---|---|---|---|---|---|---|
艾玛·威廉姆斯(Emma Williams) | F | 年龄0 | 72.65 | NA | NA | NA | NA | ||
艾玛·威廉姆斯(Emma Williams) | F | 1岁 | 82.46 | ||||||
艾玛·威廉姆斯(Emma Williams) | F | AGE2岁 | 91.76 | ||||||
艾登·琼斯(Aiden Jones) | 中号 | 年龄0 | 69.76 | NA | NA | NA | NA | NA | |
艾登·琼斯(Aiden Jones) | 中号 | 1岁 | 79.89 |
由于每一行只有一个度量, 因此你可以将它们收集到一列中, 结果将如下所示:
名称 | 性别 | 测量 | |
---|---|---|---|
艾玛·威廉姆斯(Emma Williams) | F | 年龄0 | 72.65 |
艾玛·威廉姆斯(Emma Williams) | F | 1岁 | 82.46 |
艾玛·威廉姆斯(Emma Williams) | F | AGE2岁 | 91.76 |
艾登·琼斯(Aiden Jones) | 中号 | 年龄0 | 69.76 |
艾登·琼斯(Aiden Jones) | 中号 | 1岁 | 79.89 |
让我们为所有度量创建新的列名称。通常, 它被命名为”值”:
名称 | 性别 | 测量 | 值 |
---|---|---|---|
艾玛·威廉姆斯(Emma Williams) | F | 年龄0 | 72.65 |
艾玛·威廉姆斯(Emma Williams) | F | 1岁 | 82.46 |
艾玛·威廉姆斯(Emma Williams) | F | AGE2岁 | 91.76 |
艾登·琼斯(Aiden Jones) | 中号 | 年龄0 | 69.76 |
艾登·琼斯(Aiden Jones) | 中号 | 1岁 | 79.89 |
让我们看看上表。你是否注意到”年龄”在重复?你可以省略重复的实体, 这将为你提供以下结果:
名称 | 性别 | 年龄 | 值 |
---|---|---|---|
艾玛·威廉姆斯(Emma Williams) | F | 0 | 72.65 |
艾玛·威廉姆斯(Emma Williams) | F | 1 | 82.46 |
艾玛·威廉姆斯(Emma Williams) | F | 2 | 91.76 |
艾登·琼斯(Aiden Jones) | 中号 | 0 | 69.76 |
艾登·琼斯(Aiden Jones) | 中号 | 1 | 79.89 |
在每一行中重复的年龄现在是列名。上表中的列名值可以更具体。你将其替换为高度, 这更具有启发性。你可以在下表中看到结果:
名称 | 性别 | 年龄 | 高度 |
---|---|---|---|
艾玛·威廉姆斯(Emma Williams) | F | 0 | 72.65 |
艾玛·威廉姆斯(Emma Williams) | F | 1 | 82.46 |
艾玛·威廉姆斯(Emma Williams) | F | 2 | 91.76 |
艾登·琼斯(Aiden Jones) | 中号 | 0 | 69.76 |
艾登·琼斯(Aiden Jones) | 中号 | 1 | 79.89 |
让我们将表15与表17进行比较。值(表15的列名称之一)可以表示任何含义, 但是表17的高度具有非常特殊的含义:它只能指定高度, 而表15中的值可以是任何值, 例如身高, 体重, 速度或颜色。另一种方式如下所示:
名称 | 性别 | 测量 | 值 |
---|---|---|---|
艾玛·威廉姆斯(Emma Williams) | F | 身高 | 72.65 |
艾玛·威廉姆斯(Emma Williams) | F | 身高 | 82.46 |
艾玛·威廉姆斯(Emma Williams) | F | 身高 | 91.76 |
艾登·琼斯(Aiden Jones) | 中号 | 身高 | 69.76 |
艾登·琼斯(Aiden Jones) | 中号 | 身高 | 79.89 |
让我们考虑一下其中的度量是多种多样的情况。如果测量的是身高, 体重和体重指数, 则如下表所示。但是在这种情况下, 列值具有不同比例的数值, 因此读取它们可能会造成混淆。在此表中, 身高以厘米为单位, 体重以千克为单位:
名称 | 性别 | 测量 | 值 |
---|---|---|---|
艾玛·威廉姆斯(Emma Williams) | F | 高度 | 72.65 |
艾玛·威廉姆斯(Emma Williams) | F | 重量 | 8.22 |
艾玛·威廉姆斯(Emma Williams) | F | 体重指数 | 22.60 |
艾登·琼斯(Aiden Jones) | 中号 | 高度 | 69.76 |
艾登·琼斯(Aiden Jones) | 中号 | 重量 | 8.51 |
因此, 在将宽格式转换为长格式时, 需要确定将哪些值收集到一列中。之后, 你可以确定列名称。
让我们总结一下到目前为止所讲的内容:要将width- from从long转换为long-form, 需要确定要修改的列是否位于一列中。这样做时, 许多列被合并为一列。因此, 你需要该列的列名, 你可以在下表中看到它:
id1 | id2 | 年龄0 | 1岁 | AGE2岁 |
---|---|---|---|---|
艾玛·威廉姆斯(Emma Williams) | F | NA | 82.46 | 91.76 |
艾登·琼斯(Aiden Jones) | 中号 | 69.76 | 79.89 | NA |
艾玛·威廉姆斯(Emma Williams) | F | NA | 82.46 | 91.76 |
id1 | id2 | 年龄0 | 1岁 | AGE2岁 |
---|---|---|---|---|
艾玛·威廉姆斯(Emma Williams) | F | NA | ||
艾玛·威廉姆斯(Emma Williams) | F | 82.46 | ||
艾玛·威廉姆斯(Emma Williams) | F | 91.76 | ||
艾登·琼斯(Aiden Jones) | 中号 | 69.76 | ||
艾登·琼斯(Aiden Jones) | 中号 | 79.89 | ||
艾登·琼斯(Aiden Jones) | 中号 | NA | ||
艾玛·威廉姆斯(Emma Williams) | F | NA | ||
艾玛·威廉姆斯(Emma Williams) | F | 82.46 | ||
艾玛·威廉姆斯(Emma Williams) | F | 91.76 |
id1 | id2 | 年龄_ | 年龄0 | 1岁 | AGE2岁 |
---|---|---|---|---|---|
艾玛·威廉姆斯(Emma Williams) | F | 年龄0 | NA | ||
艾玛·威廉姆斯(Emma Williams) | F | 1岁 | 82.46 | ||
艾玛·威廉姆斯(Emma Williams) | F | AGE2岁 | 91.76 | ||
艾登·琼斯(Aiden Jones) | 中号 | 年龄0 | 69.76 | ||
艾登·琼斯(Aiden Jones) | 中号 | 1岁 | 79.89 | ||
艾登·琼斯(Aiden Jones) | 中号 | AGE2岁 | NA | ||
艾玛·威廉姆斯(Emma Williams) | F | 年龄0 | NA | ||
艾玛·威廉姆斯(Emma Williams) | F | 1岁 | 82.46 | ||
艾玛·威廉姆斯(Emma Williams) | F | AGE2岁 | 91.76 |
id1 | id2 | 年龄_ | |
---|---|---|---|
艾玛·威廉姆斯(Emma Williams) | F | 年龄0 | NA |
艾玛·威廉姆斯(Emma Williams) | F | 1岁 | 82.46 |
艾玛·威廉姆斯(Emma Williams) | F | AGE2岁 | 91.76 |
艾登·琼斯(Aiden Jones) | 中号 | 年龄0 | 69.76 |
艾登·琼斯(Aiden Jones) | 中号 | 1岁 | 79.89 |
艾登·琼斯(Aiden Jones) | 中号 | AGE2岁 | NA |
艾玛·威廉姆斯(Emma Williams) | F | 年龄0 | NA |
艾玛·威廉姆斯(Emma Williams) | F | 1岁 | 82.46 |
艾玛·威廉姆斯(Emma Williams) | F | AGE2岁 | 91.76 |
id1 | id2 | 键 | 值 |
---|---|---|---|
艾玛·威廉姆斯(Emma Williams) | F | 年龄0 | NA |
艾玛·威廉姆斯(Emma Williams) | F | 1岁 | 82.46 |
艾玛·威廉姆斯(Emma Williams) | F | AGE2岁 | 91.76 |
艾登·琼斯(Aiden Jones) | 中号 | 年龄0 | 69.76 |
艾登·琼斯(Aiden Jones) | 中号 | 1岁 | 79.89 |
艾登·琼斯(Aiden Jones) | 中号 | AGE2岁 | NA |
艾玛·威廉姆斯(Emma Williams) | F | 年龄0 | NA |
艾玛·威廉姆斯(Emma Williams) | F | 1岁 | 82.46 |
艾玛·威廉姆斯(Emma Williams) | F | AGE2岁 | 91.76 |
id1 | id2 | 键 | 值 |
---|---|---|---|
艾玛·威廉姆斯(Emma Williams) | F | 1岁 | 82.46 |
艾玛·威廉姆斯(Emma Williams) | F | AGE2岁 | 91.76 |
艾登·琼斯(Aiden Jones) | 中号 | 年龄0 | 69.76 |
艾登·琼斯(Aiden Jones) | 中号 | 1岁 | 79.89 |
艾玛·威廉姆斯(Emma Williams) | F | 1岁 | 82.46 |
艾玛·威廉姆斯(Emma Williams) | F | AGE2岁 | 91.76 |
让我们看一下上表中的ID1和ID2列。 id2没有指定个人, 但它是个人的属性(性别)。换句话说, 你可以说这是一个度量。因此, 你可以将其转换为较长格式。最长格式由三列组成, 分别是id, key和value。
id | 键 | 值 |
---|---|---|
艾玛·威廉姆斯(Emma Williams) | 性别 | F |
艾玛·威廉姆斯(Emma Williams) | 1岁 | 82.46 |
艾玛·威廉姆斯(Emma Williams) | AGE2岁 | 91.76 |
艾登·琼斯(Aiden Jones) | 性别 | F |
艾登·琼斯(Aiden Jones) | 年龄0 | 69.76 |
艾登·琼斯(Aiden Jones) | 1岁 | 79.89 |
艾玛·威廉姆斯(Emma Williams) | 性别 | F |
艾玛·威廉姆斯(Emma Williams) | 1岁 | 82.46 |
艾玛·威廉姆斯(Emma Williams) | AGE2岁 | 91.76 |
上表显示了表25中最长的格式。但是不同的人可以使用相同的名字。
在这种情况下, 长格式可能会造成混淆, 因为id不能指定一个人。你可以在名称后面加上数字以区分人员(例如, 使用R函数make.unique()), 但是你无法将更改后的名称与原始名称与数字区分开。想想一个真正的名字叫” John.2″的人!
解决此问题的明显方法是为其他人分配不同的号码ID。在这种情况下, 名称是另一个度量。
下表显示, 即使名称也被视为度量。从某种意义上说, 这是真正的最长格式。
id | 键 | 值 |
---|---|---|
1 | 名称 | 艾玛·威廉姆斯(Emma Williams) |
1 | 性别 | F |
1 | 1岁 | 82.46 |
1 | AGE2岁 | 91.76 |
2 | 名称 | 艾登·琼斯(Aiden Jones) |
2 | 性别 | F |
2 | 年龄0 | 69.76 |
2 | 1岁 | 79.89 |
3 | 名称 | 艾玛·威廉姆斯(Emma Williams) |
3 | 性别 | F |
3 | 1岁 | 82.46 |
3 | AGE2岁 | 91.76 |
最长的形式是制作宽格式的最简单形式。如果将表20至表25中所示的将宽格式转换为长格式的过程反向进行, 则可以进入宽格式。下表显示了此过程:
id | 键 | 名称 | 性别 | 年龄0 | 1岁 | AGE2岁 |
---|---|---|---|---|---|---|
1 | 名称 | 艾玛·威廉姆斯(Emma Williams) | ||||
1 | 性别 | F | ||||
1 | 1岁 | 82.46 | ||||
1 | AGE2岁 | 91.76 | ||||
2 | 名称 | 艾登·琼斯(Aiden Jones) | ||||
2 | 性别 | F | ||||
2 | 年龄0 | 69.76 | ||||
2 | 1岁 | 79.89 | ||||
3 | 名称 | 艾玛·威廉姆斯(Emma Williams) | ||||
3 | 性别 | F | ||||
3 | 1岁 | 82.46 | ||||
3 | AGE2岁 | 91.76 |
id | 名称 | 性别 | 年龄0 | 1岁 | AGE2岁 |
---|---|---|---|---|---|
1 | 艾玛·威廉姆斯(Emma Williams) | ||||
1 | F | ||||
1 | 82.46 | ||||
1 | 91.76 | ||||
2 | 艾登·琼斯(Aiden Jones) | ||||
2 | F | ||||
2 | 69.76 | ||||
2 | 79.89 | ||||
3 | 艾玛·威廉姆斯(Emma Williams) | ||||
3 | F | ||||
3 | 82.46 | ||||
3 | 91.76 |
id | 名称 | 性别 | 年龄0 | 1岁 | AGE2岁 |
---|---|---|---|---|---|
1 | 艾玛·威廉姆斯(Emma Williams) | F | 82.46 | 91.76 | |
1 | |||||
1 | |||||
1 | |||||
2 | 艾登·琼斯(Aiden Jones) | F | 69.76 | 79.89 | |
2 | |||||
2 | |||||
2 | |||||
3 | 艾玛·威廉姆斯(Emma Williams) | F | 82.46 | 91.76 | |
3 | |||||
3 | |||||
3 |
id | 名称 | 性别 | 年龄0 | 1岁 | AGE2岁 |
---|---|---|---|---|---|
1 | 艾玛·威廉姆斯(Emma Williams) | F | 82.46 | 91.76 | |
2 | 艾登·琼斯(Aiden Jones) | F | 69.76 | 79.89 | |
3 | 艾玛·威廉姆斯(Emma Williams) | F | 82.46 | 91.76 |
将宽格式转换为长格式的关键因素是决定将哪些列收集为一列。
但这不必只是一栏。如有必要, 你可以使用两列, 如下表所示:
名称 | 性别 | h2011 | h2012 | w2011 | w2012 |
---|---|---|---|---|---|
杰克逊·史密斯 | 中号 | 74.69 | 84.99 | 9.60 | 12.0 |
奥利维亚·米勒(Olivia Miller) | F | NA | 80.76 | 7.15 | 10.7 |
艾娃·威尔逊(Ava Wilson) | F | 88.77 | 96.45 | NA | 15.0 |
你能把它做成长形吗?
h2011, h2012, w2011, w2012列是2011年和2012年的平均身高和体重。身高和体重的测量单位为厘米, 公斤。因此, 高度和重量都只能使用一列, 也可以在此表中使用两列:
名称 | 性别 | 年 | 高度 | 重量 |
---|---|---|---|---|
杰克逊·史密斯 | 中号 | 2011 | 74.69 | 9.60 |
杰克逊·史密斯 | 中号 | 2012 | 84.99 | 12.00 |
奥利维亚·米勒(Olivia Miller) | F | 2011 | NA | 80.76 |
奥利维亚·米勒(Olivia Miller) | F | 2012 | 7.15 | 10.70 |
艾娃·威尔逊(Ava Wilson) | F | 2011 | 88.77 | 96.45 |
艾娃·威尔逊(Ava Wilson) | F | 2012 | NA | 15.00 |
这是长格式还是宽格式?
从R中的长数据到宽数据
让我们用R进行长形和宽形之间的覆盖。有许多功能和软件包可用于此任务。
功能 | 包 | to_long_form | to_wide_form |
---|---|---|---|
堆放/堆放 | 实用程序 | 堆 | 拆箱 |
重塑 | 统计资料 | 重塑(direction =” long”, …) | 重塑(direction =” wide”, …) |
熔铸 | 重塑2 | 熔化 | 广播 |
收集/传播 | tidyr | 收集 | 传播 |
在这里, 我将解释如何使用reshape2包的melt()和dcast()函数。原因是stack()和unstack()是基本函数, 因此需要对它们的结果进行后处理。请注意, gather()和spread()是tidyr函数, 它们也非常流行, 但本教程将不介绍它们。
你可能可以使用的另一个功能是stats包随附的reshape()。实际上, 不要为此功能感到困惑, 因为还有一个名为reshape的软件包!该软件包与reshape2一起为那些为reshape()苦苦挣扎的人而开发。另外, 函数reshape()似乎假设数据是纵向的, 这意味着测量会随时间重复。
让我们将表35中的数据转换为长格式。假设下表存储了一个名为dat的data.frame。
名称 | 性别 | 年2011 | 年2012 | 年2013 |
---|---|---|---|---|
杰克逊·史密斯 | 中号 | 74.69 | 84.99 | 91.73 |
艾玛·威廉姆斯(Emma Williams) | F | NA | NA | 75.74 |
利亚姆·布朗 | 中号 | 88.24 | NA | 101.85 |
艾娃·威尔逊(Ava Wilson) | F | 88.77 | 96.45 | NA |
婴儿= data.frame(name = c(” Jackson Smith”, ” Emma Williams”, ” Liam Brown”, ” Ava Wilson”), 性别= c(” M”, ” F”, ” M”, ” F” ), year2011 = c(74.69, NA, 88.24, 88.77), year2012 = c(84.99, NA, NA, 96.45), year2013 = c(91.73, 75.74, 101.83, NA))婴儿
## name gender year2011 year2012 year2013
## 1 Jackson Smith M 74.69 84.99 91.73
## 2 Emma Williams F NA NA 75.74
## 3 Liam Brown M 88.24 NA 101.83
## 4 Ava Wilson F 88.77 96.45 NA
你要问的问题是:”哪些列合并为一个列?”。
分别是2011年, 2012年和2013年。当你使用函数melt()时, 应为measure.vars列出这些列:
melt(babies, measure.vars = c("year2011", "year2012", "year2013"))
## name gender variable value
## 1 Jackson Smith M year2011 74.69
## 2 Emma Williams F year2011 NA
## 3 Liam Brown M year2011 88.24
## 4 Ava Wilson F year2011 88.77
## 5 Jackson Smith M year2012 84.99
## 6 Emma Williams F year2012 NA
## 7 Liam Brown M year2012 NA
## 8 Ava Wilson F year2012 96.45
## 9 Jackson Smith M year2013 91.73
## 10 Emma Williams F year2013 75.74
## 11 Liam Brown M year2013 101.83
## 12 Ava Wilson F year2013 NA
year2011, year2012, year2013是位于第3、4、5th的列, 因此你可以使用:
melt(babies, measure.vars = 3:5)
## name gender variable value
## 1 Jackson Smith M year2011 74.69
## 2 Emma Williams F year2011 NA
## 3 Liam Brown M year2011 88.24
## 4 Ava Wilson F year2011 88.77
## 5 Jackson Smith M year2012 84.99
## 6 Emma Williams F year2012 NA
## 7 Liam Brown M year2012 NA
## 8 Ava Wilson F year2012 96.45
## 9 Jackson Smith M year2013 91.73
## 10 Emma Williams F year2013 75.74
## 11 Liam Brown M year2013 101.83
## 12 Ava Wilson F year2013 NA
结果在上表中。注意列名变量和值。表23和表24显示需要新的列名。函数melt()具有新列的默认名称-变量和值。你可以使用variable.name =和value.name =争论覆盖默认值。让我们在下面做这个:
melt(babies, measure.vars=3:5, variable.name="year", value.name="height")
## name gender year height
## 1 Jackson Smith M year2011 74.69
## 2 Emma Williams F year2011 NA
## 3 Liam Brown M year2011 88.24
## 4 Ava Wilson F year2011 88.77
## 5 Jackson Smith M year2012 84.99
## 6 Emma Williams F year2012 NA
## 7 Liam Brown M year2012 NA
## 8 Ava Wilson F year2012 96.45
## 9 Jackson Smith M year2013 91.73
## 10 Emma Williams F year2013 75.74
## 11 Liam Brown M year2013 101.83
## 12 Ava Wilson F year2013 NA
在上面的示例中指定了测量值。对于你要处理的那些设置, Id可以间接指定测量值。因此, 你可以选择ID列而不是度量。
两者的结果相同。第一个选择ID的列, 第二个选择要收集的列:
melt(babies, id.vars=c("name", "gender"))
melt(babies, measure.vars = c("year2011", "year2012", "year2013"))
## name gender variable value
## 1 Jackson Smith M year2011 74.69
## 2 Emma Williams F year2011 NA
## 3 Liam Brown M year2011 88.24
## 4 Ava Wilson F year2011 88.77
## 5 Jackson Smith M year2012 84.99
## 6 Emma Williams F year2012 NA
## 7 Liam Brown M year2012 NA
## 8 Ava Wilson F year2012 96.45
## 9 Jackson Smith M year2013 91.73
## 10 Emma Williams F year2013 75.74
## 11 Liam Brown M year2013 101.83
## 12 Ava Wilson F year2013 NA
如果你同时指定id.vars和measure.vars, 则其中任何未包含的列将从结果中排除。例如, 查看下面的代码块:
melt(babies, id.vars=c("name"), measure.vars=c("year2011", "year2012"))
## name variable value
## 1 Jackson Smith year2011 74.69
## 2 Emma Williams year2011 NA
## 3 Liam Brown year2011 88.24
## 4 Ava Wilson year2011 88.77
## 5 Jackson Smith year2012 84.99
## 6 Emma Williams year2012 NA
## 7 Liam Brown year2012 NA
## 8 Ava Wilson year2012 96.45
另外, na.rm = T可以消除NA:
melt(babies, id.vars=c("name"), measure.vars=c("year2011", "year2012"), na.rm=T)
## name variable value
## 1 Jackson Smith year2011 74.69
## 3 Liam Brown year2011 88.24
## 4 Ava Wilson year2011 88.77
## 5 Jackson Smith year2012 84.99
## 8 Ava Wilson year2012 96.45
dcast()函数执行与melt()相反的操作。 id, variable和value是最长格式的列。 dcast(data, id〜variable, value.var =” value”)将最长格式转换为宽格式。
babiesLong <- melt(babies, id.vars=c("name"), measure.vars=c("year2011", "year2012"), na.rm=T)
babiesLong
## name variable value
## 1 Jackson Smith year2011 74.69
## 3 Liam Brown year2011 88.24
## 4 Ava Wilson year2011 88.77
## 5 Jackson Smith year2012 84.99
## 8 Ava Wilson year2012 96.45
babiesLong的名称是id, 变量是变量, 值是值。因此, 你可以使用dcast()将其转换为长格式:
dcast(babiesLong, name ~ variable, value.var="value")
## name year2011 year2012
## 1 Ava Wilson 88.77 96.45
## 2 Jackson Smith 74.69 84.99
## 3 Liam Brown 88.24 NA
总结
似乎就是这样。在本教程中, 你专注于理解重塑数据的逻辑和过程。通常, 长格式是首选分析方法, 但也有执行方法。适当时, 宽格式的数据呈现可以节省空间, 但是随着缺失值数量的增加, 你最好转换为长格式。
对于格式转换, 你需要专注于度量值。长格式的座右铭是每行一次测量, 而宽格式的一行则有很多测量。当你对收集在一列中的所有列进行测量时, 原始列名需要保留在另一列中。当你在分散到整个列的一列中进行测量时, 你需要从可变列中找出列名称。
一旦了解了该过程, 就可以轻松使用dcast()和melt()之类的功能!