【问题标题】:Plot one column in every matrix in a list of matrices in R在 R 中的矩阵列表中的每个矩阵中绘制一列
【发布时间】:2019-01-27 20:20:29
【问题描述】:

我对编程和数据分析都很陌生,请多多包涵。我的数据目前包含 14 个矩阵 (lom) 的列表,每个矩阵对应一个国家的数据(带有两个字母的国家代码)。

这是奥地利的完整示例:

> lom["AT"]
$`AT`
   Year    AllKey    AllSub    SelKey    SelSub
1  2000  1.622279 0.5334964  1.892894 0.8057591
2  2001  1.903745 0.5827514  2.291335 0.8295899
3  2002  1.646538 0.4873866  2.006873 0.7360566
4  2003  1.405250 0.8692641  2.105648 1.2711968
5  2004  1.511154 1.5091751  1.970236 1.9407666
6  2005  1.459177 0.6781008  1.808982 1.1362805
7  2006  1.604652 0.5038658  1.942126 0.7992008
8  2007  2.107326 0.9260200  2.683072 1.3302627
9  2008  1.969735 0.6178362  2.994758 1.2051339
10 2009  1.955768 0.7365529  2.896198 1.2272024
11 2010  2.476157 0.7952590  3.715950 1.5686643
12 2011  2.092459 0.4970011  2.766169 0.6476707
13 2012  1.913122 0.5338756  2.450942 0.6022315
14 2013  2.086200 0.6739412  2.786736 0.9211941
15 2014  2.579428 0.8424793  3.152541 1.0225888
16 2015 10.662568 5.8472436  9.769320 3.8840780
17 2016 11.088286 4.6504581 10.567789 3.2383420
18 2017  7.225053 1.7528594  6.747515 1.2781224

我想根据 x = Year 和 y = 每个其他变量绘制所有 14 个国家/地区,即四个图,每个图有 14 行。因此问题标题中的要求。

我不断想出一些涉及for 循环和一些apply 函数组合的可能性,例如:

for (i in colnames(lom$anyCountry)) {
    ggplot(lapply(lom, function(x) x[,1:14], aes(x=Year, y=i)   
}

除了我现在可以看到的许多其他问题之外:

错误:data 必须是数据框,或其他可被fortify() 强制转换的对象,而不是列表

这导致我将矩阵列表组合成一个大矩阵,灵感来自 this:

bigDF <- do.call(rbind, lom)

我想我可以通过其他方式重组我的数据,也许我缺少一些有用的功能......可能两者兼而有之。对于如何尽可能有效地实现这一点,我将不胜感激。

【问题讨论】:

  • 欢迎来到 SO!这个社区有一些规则和规范,遵循它们将帮助您很好地回答您的问题。特别是,最好提供一个MCVE(一个最小的、完整的和可验证的示例)。查看this page 以获取有关 R 特定 MCVE 的提示。最好避免使用代码/数据和here's why 的图像。谢谢,祝你好运!
  • 谢谢@DanY!真的很有用,我以前从未发布过,因为提供“测试”代码似乎已经够难了……我想我现在有一些很好的指示! :)

标签: r matrix ggplot2


【解决方案1】:

考虑将所有矩阵数据附加到具有国家/地区指标的主数据框中,您可以将其用于线图的颜色参数:

# CREATE LARGE DATAFRAME FROM MATRIX LIST
lom_df <- do.call(rbind, lapply(lom, data.frame))

# CREATE COLUMN NAMES FROM ROWNAMES
lom_df$country <- gsub("\\..*$", "", row.names(lom_df))
row.names(lom_df) <- NULL

# EXTRACT ALL FOUR Y COLUMN NAMES (MINUS Year AND country)
y_columns <- colnames(lom_df[2:(ncol(lom_df)-1)])

# PRODUCE LIST OF FOUR PLOTS EACH WITH COUNTRY LINES
plot_list <- lapply(y_columns, function(col)
  ggplot(lom_df, aes_string(x="Year", y=col, color="country")) +
     geom_line()
)

# OUTPUT EACH LIST 
plot_list

【讨论】:

  • 非常感谢!那确实是冻糕! :D 简洁明了,开箱即用。我有几个后续问题,可能是相关的。为什么需要 lapply?我想我和do.call(rbind, lom) 一样吗?在正则表达式上,我看到它有效......但我很困惑,所以我问一个单独的问题,因为这里没有空间。
  • 抱歉,经过一番折腾,我确实理解了正则表达式。最后总是需要 $ 吗?
  • 很高兴听到解决方案有效!作为一个循环,lapply 用于遍历列,而正则表达式中的$ 用于指示字符串的结尾,在某些情况下可能不需要。
【解决方案2】:

此解决方案使用包ggplot2

它有两个步骤,数据准备和绘图。

首先必须将列表转换为一个大数据框,其中一列作为 id 列。我已经在 SO 中搜索了一个可以执行此操作但找不到的函数,所以就到这里了。

rbindWithID <- function(x, id.name = "ID", sep = "."){
    if(is.null(names(x))) names(x) <- paste(id.name, seq_along(x), sep = sep)
    res <- lapply(names(x), function(nm){
        DF <- x[[nm]]
        DF[[id.name]] <- nm
        x[[nm]] <- cbind(DF[ncol(DF)], DF[-ncol(DF)])
        x[[nm]]
    })
    do.call(rbind, res)
}

lom_df <- rbindWithID(lom, "Country")

现在将数据框从宽改成长。

molten <- reshape2::melt(lom_df, id.vars = c("Country", "Year"))

最后,绘制它。

library(ggplot2)

ggplot(molten, aes(Year, value, colour = Country)) +
    geom_line() +
    facet_wrap(~ variable)

数据。

set.seed(1234)    # Make the results reproducible

lom <- lapply(1:4, function(i){
    data.frame(
        Year = 2000:2008,
        AllKey = runif(9, 1, 2),
        AllSub = runif(9, 0, 2),
        SelKey = runif(9, 1, 2),
        SelSub = runif(9, 0, 2)
    )
})

names(lom) <- c("AT", "DE", "FR", "PT")

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-05-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-15
    • 1970-01-01
    相关资源
    最近更新 更多