使用geom_line()连接所选NA之间的点。

8
我的问题与Connecting across missing values with geom_line密切相关,但这是一个后续问题而不是重复问题。我的数据中有缺失值NA。使用reshape2软件包将数据长形式“融合”,并使用ggplot2同时绘制geom_points()geom_line()。在示例数据中,我只有一个组,在真实数据中,我有多个组。我想绘制一个geom_line()连接数据点,这些数据点之间的缺失数据不超过4年。换句话说,如果有3个相邻的NA行,请对数据框应用na.rm操作,而如果至少有4个相邻的NA行,则不要对数据框应用na.rm操作。
编辑:注意:我正在复制一本书中的图表,即使数据丢失,也会连接点。最好使用不同的linetypecolour表示连接缺失数据的线段,并在图例中说明。
以下是一种非常繁琐丑陋的hack方法,无法扩展到大量数据的操作。我将感激不尽,如果您能提供更简单的方法,尤其是找到一种简单方法来计算数据中连续NAs的实例。
### ggplot draws geom_line with NAs

# Data (real-world example, so not exactly MWE)
df <- 
structure(list(Year = c(1910, 1911, 1912, 1913, 1914, 1915, 1916, 
1917, 1918, 1919, 1920, 1921, 1922, 1923, 1924, 1925, 1926, 1927, 
1928, 1929, 1930, 1931, 1932, 1933, 1934, 1935, 1936, 1937, 1938, 
1939, 1940, 1941, 1942, 1943, 1944, 1945, 1946, 1947, 1948, 1949, 
1950, 1951, 1952, 1953, 1954, 1955, 1956, 1957, 1958, 1959, 1960, 
1961, 1962, 1963, 1964, 1965, 1966, 1967, 1968, 1969, 1970, 1971, 
1972, 1973, 1974, 1975, 1976, 1977, 1978, 1979, 1980, 1981, 1982, 
1983, 1984, 1985, 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 
1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 
2005, 2006, 2007, 2008, 2009, 2010), variable = structure(c(2L, 
2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
2L, 2L, 2L, 2L), .Label = c("France", "Germany", "Sweden", "Japan"
), class = c("ordered", "factor")), value = c(0.1724, 0.1748, 
0.1752, 0.1777, 0.1778, 0.1953, 0.2132, 0.2242, 0.222, 0.1947, 
NA, NA, NA, NA, NA, 0.113, 0.113, 0.115, 0.112, 0.111, NA, NA, 
0.114, 0.109, 0.113, 0.12, 0.137, 0.15, 0.163, NA, NA, NA, NA, 
NA, NA, NA, NA, NA, NA, NA, 0.116, NA, NA, NA, NA, NA, NA, 0.11, 
NA, NA, NA, 0.122, NA, NA, NA, 0.122, NA, NA, 0.112, NA, NA, 
0.113, NA, NA, 0.101, NA, NA, 0.102, NA, NA, 0.1043, NA, NA, 
0.0906, NA, NA, 0.0964, NA, NA, 0.1052, NA, NA, 0.1043, NA, NA, 
0.1005, NA, NA, 0.1088, NA, NA, 0.101139312657167, 0.0950290025146689, 
0.0901042749371333, 0.09, 0.107249622799665, 0.108891198658843, 
0.115913495389774, 0.110684772282761, 0.113299133836267, 0.111991953059514
)), .Names = c("Year", "variable", "value"), row.names = 102:202, class = "data.frame")

默认绘图:
library("ggplot2")
ggplot(data = df, aes(x = Year, y = value, group = variable, colour = variable, shape = variable)) + 
    geom_point(size = 3) + geom_line()

在去除所有缺失值后的图形(请参见连接带有geom_line的缺失值):

在去除所有缺失值后的情况下,图形如上所示(请参见使用geom_line连接缺失值):

ggplot(data = df, aes(x = Year, y = value, group = variable, colour = variable, shape = variable)) + 
    geom_point(size = 3) + geom_line(data = df[!is.na(df$value), ])

在这里输入图片描述

所需绘图:


注:该内容涉及IT技术,可能需要专业词汇。
df2 <- df
df2[df2$Year == 1922, ]$value <- "-999999"
df2[df2$Year == 1948, ]$value <- "-999999"
df2 <- df2[!is.na(df2$value), ]
df2$value <- as.numeric(df2$value)
ggplot(data = df2, aes(x = Year, y = value, group = variable, colour = variable, shape = variable)) + geom_point(size = 3) + 
    geom_line() + scale_y_continuous(limit = c(.08, .23))

enter image description here


1
您所期望的图表与小时规则不一致。1950年的数据点应该被孤立,因为1939年至1949年和1951年至1956年的数据都是“NA”,这两个时间段都是>3个“NA”的序列。 - jlhoward
1个回答

7
这将生成您的“预期图表”,不过请注意评论中提到的例外情况。
x <- rle(!is.na(df$value))
x$values[which(x$lengths>3 & !x$values)] <- TRUE
indx <- inverse.rle(x)
library(ggplot2)
ggplot(df[indx,],aes(x=Year,y=value,color=variable))+
  geom_point(size=3)+
  geom_line()

基本上,我们将NA编码为FALSE,将其他所有内容编码为TRUE,然后执行运行长度编码以识别T/F序列。任何长度>3的FALSE序列都应该保留,因此我们将它们转换为TRUE(就像它们不是NA一样),然后我们使用反向rle恢复一个索引向量,其中TRUE表示应该保留该行。最后,我们将此应用于ggplot中使用的df


非常好,感谢您的解释:我以前没有听说过“rle”函数,这将非常有用。您对我的选择规则不一致的口头描述也非常准确! - PatrickT
我不完全理解它是如何工作的,但它非常好,并且我认为我大致明白了。是否有一种方法可以将其放入一个函数中,根据datay输入产生geom_line()所需的输出,以跳过NA?基本上,我想能够调用ggplot(function(my.data), aes(x,y)) + geom_line()。有办法吗? - Dr. Fabian Habersack

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接