r语言tidyr
这是墨菲的数据定律:您拥有的数据并不总是符合您所需的格式。 并非所有问题都与数据中的错误或空白有关。 有时候,你有广泛的数据需要被长 ; 或需要广泛的长数据。
让我们来研究一个例子。 在这里,我将阅读五个美国大都市地区的房价电子表格:波士顿,底特律,费城,旧金山和圣何塞(我称其为硅谷)。 更具体地说,是每两年一次的房价数据,1995年所有城市的房价指数均始于100。该数据从2000年到2018年。
看一下电子表格:
IDG
具有宽格式数据的Excel电子表格
我使用housing_data <- rio::import("housingPrices.xlsx")
导入此数据。 如果您想在没有电子表格的情况下继续进行操作,那么创建此数据框的代码位于本文的底部。
这是一种非常人性化的格式。 有时称为“宽”格式。 每个都会区都有其自己的列,您可以向下浏览每列并查看该都会区的移动。
但是,如果要使用ggplot2绘制图形,则需要采用所谓的整齐或“长”格式的数据。 每行只有一个观察值,列名中没有数据。 因此,您可以轻松按城市区分ggplot2颜色。 现在,城市信息位于列名中,而不是数据本身。
另一个例子:如果我想计算每年哪个城市的指数值最高,那么很容易计算出每一行中哪个城市的指数最高。 但是,如果要显示哪个都市区域的索引值最高,则必须从列名称中提取信息。
这是此数据的简洁版本。
IDG
具有整齐或长格式的数据的电子表格
每行一个观察值:季度,房价指数值和都会区。 对于一个人而言,扫描并不那么容易,但是对于使用R分析(尤其是使用tidyverse程序包)则要好得多。
因此,如果数据的唯一版本是宽版本,那么如何获得长版本? 一种方式是与tidyr包的gather
功能。
gather()
至少包含三个参数:第一个是数据框的名称。 第二个是您要用于新类别列的名称,称为键。 第三是新值列所需的名称,称为值。 之后是您要“聚集”到新的键和值列中的所有列。 如果您不提供任何列名,则将收集所有列。 在这种情况下,我们希望收集所有城市列,而不是四分之一列。 我可以用-Quarter
排除它。
这段代码创建了一个长整洁的数据版本:
library(tidyr)
housing_data_tidy <- gather(data = housing_data,
key = MetroArea, value = IndexValue, -Quarter)
使用ggplot2绘制此版本要容易得多。 只需添加group = MetroArea
,我的图表就会将每个都会区绘制为自己的系列或线条。 color = MetroArea
为每行赋予不同的颜色。
library(ggplot2)
ggplot(housing_data_tidy) +
geom_line(aes(x = Quarter, y = IndexValue,
group = MetroArea, color = MetroArea))
以下代码为绘图增加了一些自定义:
ggplot(housing_data_tidy) +
geom_line(aes(x = Quarter, y = IndexValue,
group = MetroArea, color = MetroArea)) +
theme_minimal() +
theme(panel.border = element_blank(),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
axis.line = element_line(colour = "gray")) +
ylab("") +
ggtitle("Change in Home Prices in 5 US Metro Areas",
subtitle = "Data measured January every 2 years;
index starts in 1995 at 100") +
theme(plot.title = element_text(hjust = 0.5), plot.subtitle = element_text(hjust = 0.5))
我选择了一个不同的主题,然后通过删除所有背景网格和y轴标签,添加标题和副标题以及将标题和副标题居中进行了调整。 在我重塑之前,我想向您展示一个与ggplot2一起使用的很酷的程序包,称为Directlabels。
在这里,我使用的是刚刚制作的相同的自定义图,但是将其存储在名为my_customized_plot
的变量中。 然后,在其上运行direct.label()
函数,并使用参数last.points
和文本的稍微水平对齐。
library("directlabels")
my_customized_plot <- ggplot(housing_data_tidy) +
geom_line(aes(x = Quarter, y = IndexValue,
group = MetroArea, color = MetroArea)) +
theme_minimal() +
theme(panel.border = element_blank(),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
axis.line = element_line(colour = "gray")) +
ylab("") +
ggtitle("Change in Home Prices in 5 US Metro Areas",
subtitle = "Data measured January every 2 years;
index starts in 1995 at 100") +
theme(plot.title = element_text(hjust = 0.5),
plot.subtitle = element_text(hjust = 0.5))
direct.label(my_customized_plot, list(last.points, hjust = -0.1))
这是发生了什么:
IDG
ggplot2折线图和directlabels软件包
我为每行贴上了一个漂亮的标签,而不是一个传奇! 我很喜欢在某些情节中选择它。
回到重塑。
假设我从一开始就将其作为整洁的数据开始,但是想要使其“宽泛”以创建易于阅读的表格。 基本上从现在的长数据框到第一个版本,我在每个都会区的单独列中显示了该版本。 为此,您需要gather()
的反面,即spread()
。
spread()
还将数据,键和值作为参数。 在这种情况下,数据就是您的整洁数据帧。 键是现有列的名称,您希望将每个值都变成自己的列。 对于此数据,它是MetroArea。 我们有一列包含都市圈,我希望每个都市圈都在其自己的列中。 值是现有列的名称,其中包含应散布到新列中的值。 除非您告诉R,否则R可能不确定是否应该将其指定为Index列或Quarter列。
这是代码:
housing_data_wide <- spread(housing_data_tidy,
key = MetroArea, value = IndexValue)
现在我们回到广泛的数据。
创建初始数据框的代码
housing_data <- data.frame(stringsAsFactors=FALSE,
Quarter = c("Q1-2000", "Q1-2002", "Q1-2004", "Q1-2006", "Q1-2008",
"Q1-2010", "Q1-2012", "Q1-2014", "Q1-2016", "Q1-2018"),
Boston = c(148.58, 189.41, 234.68, 272.14, 253.33, 227.91, 224.55,
237.61, 264.23, 300.96),
Detroit = c(150.8, 170.34, 181.89, 186.43, 158.29, 117.45, 111.14, 130.59,
148.26, 170.92),
Phil = c(111.73, 132.86, 164.54, 219.74, 234.13, 219.46, 211.24,
214.87, 227.5, 258.49),
SanFran = c(159.11, 195.5, 223.02, 305.88, 291.35, 248.28, 238.37, 306.24,
387.34, 447.45),
SiValley = c(170.74, 205.14, 223.33, 311.17, 293.01, 238.12, 233, 300.89,
367.1, 428.45))
翻译自: https://www.infoworld.com/article/3310078/reshape-data-in-r-with-the-tidyr-package.html
r语言tidyr