【问题标题】:How to perform a calculation for all columns of a matrix?如何对矩阵的所有列执行计算?
【发布时间】:2019-08-30 11:09:40
【问题描述】:

我有一个 66 棵树的年轮宽度矩阵。行代表测量的年份,列代表不同的树。

现在我想逐棵计算从一年到另一棵树的生长差异。我设法通过dplyr 中的“滞后”功能分别为每一列做到了这一点。为 66 列编写的代码很多,所以我正在寻找一种方法来一次为所有列执行此操作,但逐列。

我的“treegrowth”data.frame 如下所示:

year tree1 tree2 tree3 ...
1900 0.72 0.34 1.34
1901 0.56 0.88 0.98
1902 1.23 0.56 1.67
...

对于每棵树,我想将一年的值除以前一年的值,并将旧值与结果子集。

我可以像这样对每一列都这样做:

  treegrowth$tree1 <- treegrowth$tree1 / lag(treegrowth$tree1)

但是我怎样才能一步完成所有树(列)的管理?

如果我忽略了'$tree1',就会发生一些奇怪的事情,但不是我想要的。

> dput(head(treegrowth))
structure(list(WA12M = c(NA_real_, NA_real_, NA_real_, NA_real_, 
NA_real_, NA_real_), WA81M = c(NA_real_, NA_real_, NA_real_, 
NA_real_, NA_real_, NA_real_), WA101M = c(NA_real_, NA_real_, 
NA_real_, NA_real_, NA_real_, NA_real_), HA263M = c(NA_real_, 
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), HA358M = c(NA_real_, 
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), HA386M = c(NA_real_, 
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), HA387M = c(NA_real_, 
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), HA388M = c(0.73, 
0.73, 0.84, 0.43, 0.67, 0.72), HA390M = c(NA_real_, NA_real_, 
NA_real_, NA_real_, NA_real_, NA_real_), HA420M = c(NA_real_, 
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), MI49M = c(NA_real_, 
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), MI51M = c(NA_real_, 
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), MI62M = c(NA_real_, 
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), MI309M = c(NA_real_, 
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), NO4M = c(NA_real_, 
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), NO8M = c(NA_real_, 
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), NO23M = c(NA_real_, 
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), NO42M = c(NA_real_, 
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), NO47M = c(NA_real_, 
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), NO50M = c(NA_real_, 
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), NO73M = c(NA_real_, 
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), WA3M = c(NA_real_, 
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), WA18M = c(NA_real_, 
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), WA22M = c(NA_real_, 
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), WA25M = c(NA_real_, 
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), WA26M = c(NA_real_, 
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), WA27M = c(NA_real_, 
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), WA28M = c(NA_real_, 
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), WA38M = c(NA_real_, 
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), WA40M = c(NA_real_, 
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), WA48M = c(NA_real_, 
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), WA64M = c(NA_real_, 
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), WA80M = c(NA_real_, 
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), WA84M = c(NA_real_, 
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), WA88M = c(NA_real_, 
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), WA90M = c(NA_real_, 
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), WA93M = c(NA_real_, 
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), WA95M = c(NA_real_, 
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), WA103M = c(NA_real_, 
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), WA104M = c(NA_real_, 
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), WA111M = c(NA_real_, 
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), WA141M = c(NA_real_, 
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), WA142M = c(NA_real_, 
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), WA154M = c(NA_real_, 
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), WA163M = c(NA_real_, 
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), WA164M = c(NA_real_, 
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), WA177M = c(NA_real_, 
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), WA194M = c(NA_real_, 
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), WA195M = c(NA_real_, 
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), WA196M = c(NA_real_, 
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), WA197M = c(NA_real_, 
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), WA198M = c(NA_real_, 
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), WA200M = c(NA_real_, 
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), WA202M = c(NA_real_, 
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), WA205M = c(NA_real_, 
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), WA206M = c(NA_real_, 
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), WA207M = c(NA_real_, 
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), WA225M = c(NA_real_, 
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), WA252M = c(NA_real_, 
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), WA291M = c(NA_real_, 
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), WA294M = c(NA_real_, 
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), WA297M = c(NA_real_, 
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), WA299M = c(NA_real_, 
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), WA376M = c(NA_real_, 
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), WA379M = c(NA_real_, 
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), WA395M = c(NA_real_, 
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), EI33M = c(NA_real_, 
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), EI38M = c(NA_real_, 
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), HA161M = c(NA_real_, 
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_)), row.names`c("1803", 
"1804", "1805", "1806", "1807", "1808"), class = c("rwl", "data.frame"
))

【问题讨论】:

  • sapply(treegrowth[-1], function(x) x/lag(x))

标签: r matrix dplyr lag


【解决方案1】:

使用base R,我们可以使用lapply

treegrowth[paste0(names(df[-1]), "_growth")] <- lapply(treegrowth[-1], 
                  function(x) c(NA, x[-1]/x[-length(x)]))

#  year tree1 tree2 tree3 tree1_growth tree2_growth tree3_growth
#1 1900  0.72  0.34  1.34           NA           NA           NA
#2 1901  0.56  0.88  0.98    0.7777778    2.5882353    0.7313433
#3 1902  1.23  0.56  1.67    2.1964286    0.6363636    1.7040816

或者如果你想使用dplyrlag,我们可以使用mutate_at

library(dplyr)
treegrowth %>% mutate_at(-1, list(growth = ~./lag(.)))

数据

treegrowth <- structure(list(year = 1900:1902, tree1 = c(0.72, 0.56, 1.23), 
tree2 = c(0.34, 0.88, 0.56), tree3 = c(1.34, 0.98, 1.67)), 
class = "data.frame", row.names = c(NA, -3L))

【讨论】:

  • 谢谢! 'mutate_at' 的方式是有效的,但我用它来丢失年份​​名称。你也可以帮忙吗?
  • @ansa 第一列的“年份名称”是什么意思?对我来说似乎保持不变。 class(treegrowth$year) 是什么?您还有其他列吗?
  • 对不起,我问的不清楚。我是 R 的新手。我把表格写错了,年份不是第一列而是行的名称。这样更好理解吗?如果我使用你的代码,结果行的编号从 1 到 214(因为我有 214 年的数据)但缺少确切的年份。第一棵树也没有进行计算。我猜是因为你的代码中的“-1”,所以排除第一列是因为你认为这是年份,对吧?
  • @ansa 那么你想排除两列吗?你可以为此做treegrowth[-c(1:2)]。使用dplyr 很容易,您可以执行treegrowth %&gt;% mutate_at(-c(1, 2), list(growth = ~./lag(.))) 以便忽略第一列两列。
  • 不,我不想排除任何列。我想对所有列进行计算,但保留行名,即年份。
【解决方案2】:

zoo 包有 diff.zooarithmetic=FALSE 参数正是这样做的。使用treegrowth 在最后的注释中重复给出,我们使用以下代码将其读入动物园对象,然后应用diff

(请注意,如果需要,fortify.zoo 会将动物园对象转换为数据框。)

library(zoo)

z <- read.zoo(as.data.frame(treegrowth))
zd <- diff(z, arithmetic = FALSE)

给这个动物园对象:

zd
##          tree1     tree2     tree3
## 1901 0.7777778 2.5882353 0.7313433
## 1902 2.1964286 0.6363636 1.7040816

library(ggplot2)

autoplot(zd, facet = NULL) +
  geom_point() +
  scale_x_continuous(breaks = time(zd)) +
  xlab("year")

注意

Lines <- "year tree1 tree2 tree3
1900 0.72 0.34 1.34
1901 0.56 0.88 0.98
1902 1.23 0.56 1.67"
treegrowth <- as.matrix(read.table(text = Lines, header = TRUE))

【讨论】:

    【解决方案3】:

    您可以尝试使用 melt 函数(来自 reshape2 包)将数据帧的格式更改为长格式。 一旦采用长格式,您就可以使用循环轻松执行计算。

    如果你的树名变成你的变量,你可以写类似

    for (tree in levels(treegrowth_m$variable)){
        treegrowth_m$tree <- treegrowth_m$tree / lag(treegrowth_m$tree)
    }
    

    treegrowth_m 是你融化的 df

    【讨论】:

      【解决方案4】:

      如果您将数据重新整形为更长的格式,这会变得更容易:

      df %>% 
        gather("tree", "width", -year) %>% 
        group_by(tree) %>% 
        mutate(growth = width / lag(width))
      

      【讨论】:

        【解决方案5】:

        你可以试试下面的代码:

        treeGrowth <- data.frame("year"=c(1900, 1901, 1902), 
                                 "tree1"=c(0.72, 0.56, 1.23), 
                                 "tree2"=c(0.34, 0.88, 0.56), 
                                 "tree3"=c(1.34, 0.98, 1.67))
        
        for(column in colnames(treeGrowth)[-1]){
            treeGrowth[, paste0(column, "_growth")] <- c(NA, treeGrowth[-1, column] /     
                                                             treeGrowth[-nrow(data), 
                                                                        column])
        }
        
        print(treeGrowth)
        
        #  year tree1 tree2 tree3 tree1_growth tree2_growth tree3_growth
        #1 1900  0.72  0.34  1.34    1.0000000    1.0000000    1.0000000
        #2 1901  0.56  0.88  0.98    0.7777778    2.5882353    0.7313433
        #3 1902  1.23  0.56  1.67    2.1964286    0.6363636    1.7040816
        

        【讨论】:

          猜你喜欢
          • 2019-10-11
          • 2021-11-08
          • 2021-05-23
          • 1970-01-01
          • 1970-01-01
          • 2013-05-12
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多