对数到data.frame中的行

时间:2018-02-09 11:34:01

标签: r dplyr data-manipulation

我有一个类似矩阵的数据框,附加一列表示时间。它包含有关特定学校注册学生人数的信息,从5年级(A栏)到9年级(E栏)。

  time    A    B    C    D    E
1   13 1842 1844 1689 1776 1716
2   14 1898 1785 1807 1617 1679
3   15 2065 1865 1748 1731 1590
4   16 2215 1994 1811 1708 1703
5   17 2174 2122 1903 1765 1699

我需要随着时间的推移追踪队列的大小,这意味着我需要从6到9年级开始每年有多少五年级学生留在学校的行数信息。例如,对于那个队列2013年开始上五年级,我想了解2014年六年级中剩下多少人的信息,等等。

预期输出

这就是我想要的结果:

  start.time point.A point.B point.C point.D point.E
1         13    1842    1785    1748    1708    1699
2         14    1898    1865    1811    1765      NA
3         15    2065    1811    1765      NA      NA
4         16    2215    1765      NA      NA      NA
5         17    2174      NA      NA      NA      NA

我从diag()查看base.R,但我只能从主对角线获取数据。理想情况下,我想使用dplyr语法和管道来完成此任务。

数据

structure(list(time = 13:17, A = c(1842, 1898, 2065, 2215, 2174), B = c(1844, 1785, 1865, 1994, 2122), C = c(1689, 1807, 1748, 1811, 1903), D = c(1776, 1617, 1731, 1708, 1765), E = c(1716, 1679, 1590, 1703, 1699)), class = c("grouped_df", "tbl_df", "tbl", "data.frame"), row.names = c(NA, -5L), vars = "time", drop = TRUE, indices = list(
0L, 1L, 2L, 3L, 4L), group_sizes = c(1L, 1L, 1L, 1L, 1L), biggest_group_size = 1L, labels = structure(list(
time = 13:17), class = "data.frame", row.names = c(NA, -5L), vars = "time", drop = TRUE, .Names = "time"), .Names = c("time", "A", "B", "C", "D", "E"))

4 个答案:

答案 0 :(得分:5)

将第一列以外的输入DF转换为矩阵mat。然后,由于row(mat) - col(mat)在对角线split上相对于tsL中创建ts类序列列表而言是恒定的。我们使用cbind类,因为我们可以稍后row(mat) - col(mat) >= 0使用它们,即使它们的长度不同。对象cbind是我们想要的唯一对象,所以将它们DF组合在一起并转换结果。然后替换mat <- as.matrix(DF[-1]) L <- lapply(split(mat, row(mat) - col(mat)), ts) replace(DF, -1, t(do.call("cbind", L[as.numeric(names(L)) >= 0]))) 中的所有列,除了第一列。没有包使用。

  time    A    B    C    D    E
1   13 1842 1785 1748 1708 1699
2   14 1898 1865 1811 1765   NA
3   15 2065 1994 1903   NA   NA
4   16 2215 2122   NA   NA   NA
5   17 2174   NA   NA   NA   NA

,并提供:

#include <iostream>
#include <string>

template<int T, int U>
void foo(T a, U b)
{
    std::cout << a+b << std::endl;
}

int main() {
    foo(2,4);
    return 0;
}

答案 1 :(得分:2)

由于您在问题中提及了dplyr,因此您可以使用dplyr::lead将列B的值分别转换为E 1,2等。然后将结果与原始数据中的列timeA绑定,如下所示

library(tidyverse)
bind_cols(df[, 1:2], map2_df(.x = df[, c(3:ncol(df))],
                             .y = seq_along(df[, 3:ncol(df)]), 
                             .f = ~dplyr::lead(x = .x, n = .y)))
#  A tibble: 5 x 6
#  Groups:   time [5]
#   time     A     B     C     D     E
#  <int> <dbl> <dbl> <dbl> <dbl> <dbl>
#1    13  1842  1785  1748  1708  1699
#2    14  1898  1865  1811  1765    NA
#3    15  2065  1994  1903    NA    NA
#4    16  2215  2122    NA    NA    NA
#5    17  2174    NA    NA    NA    NA

请注意,您的数据按照您提供的方式按time分组。

答案 2 :(得分:1)

通过一些分组和整理以及row_number(),我们可以使用dplyrtidyr执行此操作,并且我们不会丢失值。

看起来有点乱,但在这里我创建了一个二维索引,其中第二个维度被反转。当这些索引位置相加时,我们得到对角行的匹配值。

data %>% 
  ungroup() %>% 
  mutate(row = row_number()) %>% 
  gather(class, stud, A:E) %>% 
  arrange(row, desc(class)) %>% 
  group_by(row) %>% 
  mutate(time_left = row_number()) %>% 
  ungroup() %>% 
  transmute(time, class, stud, start_year = time_left + row - 1) %>% 
  ggplot(aes(time, stud, color = factor(start_year))) +
  geom_line() +
  geom_point()

enter image description here

答案 3 :(得分:0)

替换&#34; d&#34;的镜像上三角形。使用下三角形的值。

m <- as.matrix(d[-1])
d[-1] <- NA
d[-1][upper.tri(m, diag = TRUE)[ , ncol(m):1]] <- m[lower.tri(m, diag = TRUE)]

#   time    A    B    C    D    E
# 1   13 1842 1785 1748 1708 1699
# 2   14 1898 1865 1811 1765   NA
# 3   15 2065 1994 1903   NA   NA
# 4   16 2215 2122   NA   NA   NA
# 5   17 2174   NA   NA   NA   NA