【问题标题】:Apply operation on all pairs of rows对所有行对应用操作
【发布时间】:2020-05-21 11:43:22
【问题描述】:

我有一个这种格式的小标题:

   position condition replicate  value
   <dbl>    <chr>     <chr>      <dbl>
 1 10       1         a          0.16
 2 10       1         b          0.21
 3 10       2         a          0.19
 4 10       2         b          0.38
 5 10       3         a          0.12
 6 10       3         b          0.35
 7 20       1         a          0.22
 8 20       1         b          0.24
 9 20       2         a          0.56
10 20       2         b          0.47
11 20       3         a          0.14
12 20       3         b          0.23
 ...

由此我想得到每个位置每对条件的所有重复对之间的差异:

   position  1.a-2.a  1.a-2.b  1.b-2.a  1.b-2.b  1.a-3.a  1.a-3.b  1.b-3.a  1.b-3.b ...
   <dbl>     <dbl>    <dbl>    <dbl>    <dbl>    <dbl>    <dbl>    <dbl>    <dbl>
 1 10        0.13     0.21     0.13     0.16     ...      ...      ...      ...
 2 20        ...      ...      ...      ...      ...      ...      ...      ...
 3 30        ...      ...      ...      ...      ...      ...      ...      ...
 ...

然后总结得到每个位置每对条件的中位数:

   position  median(abs(1.a-2.a), abs(1.a-2.b), abs(1.b-2.a), abs(1.b-2.b)) ...
   <dbl>     <dbl>
 1 10        0.0161
 2 20        ...
 3 30        ...
 ...

我尝试table %&gt;% spread(replicate, value) 将复制值分散到列中,但我不知道从那里去哪里。我需要使解决方案可推广,因为我不知道我将拥有多少条件或复制。我怎样才能做到这一点?

编辑:

类似这样的:

table %>%
  unite(condition.replicate, c(condition, replicate), sep = ".") %>%
  spread(condition.replicate, value) %>% group_by(position) %>%
  uncount(2)

给我这个:

    position  `1.a`   `1.b`  `2.a`  `2.b`  ...
    <dbl>     <dbl>   <dbl>  <dbl>  <dbl>
1   10        0.16    0.14   0.61   0.86
2   10        0.16    0.14   0.61   0.86

也许有一种方法可以重复列,使它们像这样重叠:

    position  `1.a`   `1.b`  `2.a`  `2.b`  `1.a`   `1.b`  `2.a`  `2.b` ...
    <dbl>     <dbl>   <dbl>  <dbl>  <dbl>  <dbl>   <dbl>  <dbl>  <dbl>
1   10        0.16    0.14   0.61   0.86   0.16    0.14   0.61   0.86
2   10        0.16    0.16   0.16   0.16   0.14    0.14   0.14   0.14
    position  `1.a`   `1.a`  `1.a`  `1.a`  `1.b`   `1.b`  `1.b`  `1.b` ...

然后我可以summarize 并获取行之间的差异。

【问题讨论】:

  • 什么是“一对复制品”? (你想要创造差异的那个)
  • 也许有我没有遵循的逻辑,因为将其转换为宽形数据似乎会使您的工作更加困难和混乱。制作一个条件变量并将复制粘贴在一起,获取差异,然后进行任何汇总计算。在这一点上,如果我的想法正确的话,你只希望有 2 列
  • “一对重复”是一对条件中的一对重复。例如 1.a 和 2.a,或 1.a 和 2.b,或 2.b 和 3.b,等等。
  • 另外,重复的行名是怎么回事?我尝试将其复制为文本并使用read.table 将其读入,但行名会导致错误。 dput 在数据上将更容易重新创建
  • 格式错误,现已修复。

标签: r dplyr tidyr tibble


【解决方案1】:

您可以使用嵌套的lapply 轻松制作差异矩阵:

# Make result matrix
result <- do.call(rbind, 
                  lapply(split(df, df$position), function(x)
                    do.call(c, lapply(x$value, 
                                      function(y) y - x$value))))

名字有点难

# Names for result matrix
df$unique_mix <- paste0(df$condition, ".", df$replicate)
combos <- expand.grid(unique(df$unique_mix), unique(df$unique_mix)) 
colnames(result) <- paste(combos[,1], "-", combos[,2])

但这应该会给你一些你可以使用的东西:

#>    1.a - 1.a 1.b - 1.a 2.a - 1.a 2.b - 1.a 3.a - 1.a 3.b - 1.a 1.a - 1.b 1.b - 1.b
#> 10         0     -0.05     -0.03     -0.22      0.04     -0.19      0.05         0
#> 20         0     -0.02     -0.34     -0.25      0.08     -0.01      0.02         0
#>    2.a - 1.b 2.b - 1.b 3.a - 1.b 3.b - 1.b 1.a - 2.a 1.b - 2.a 2.a - 2.a 2.b - 2.a
#> 10      0.02     -0.17      0.09     -0.14      0.03     -0.02         0     -0.19
#> 20     -0.32     -0.23      0.10      0.01      0.34      0.32         0      0.09
#>    3.a - 2.a 3.b - 2.a 1.a - 2.b 1.b - 2.b 2.a - 2.b 2.b - 2.b 3.a - 2.b 3.b - 2.b
#> 10      0.07     -0.16      0.22      0.17      0.19         0      0.26      0.03
#> 20      0.42      0.33      0.25      0.23     -0.09         0      0.33      0.24
#>    1.a - 3.a 1.b - 3.a 2.a - 3.a 2.b - 3.a 3.a - 3.a 3.b - 3.a 1.a - 3.b 1.b - 3.b
#> 10     -0.04     -0.09     -0.07     -0.26         0     -0.23      0.19      0.14
#> 20     -0.08     -0.10     -0.42     -0.33         0     -0.09      0.01     -0.01
#>    2.a - 3.b 2.b - 3.b 3.a - 3.b 3.b - 3.b
#> 10      0.16     -0.03      0.23         0
#> 20     -0.33     -0.24      0.09         0

【讨论】:

    【解决方案2】:

    如果您使用tidyverse,您可以尝试这种方法。它不是那么好,但它可能会给你你想要的。

    library(tidyverse)
    
    wide_df <- df %>%
      unite(con_rep, c(condition, replicate), sep = ".") %>%
      pivot_wider(id_cols = position, names_from = con_rep, values_from = value) %>%
      as.data.frame(.)
    
    data.frame(position = wide_df$position, combn(wide_df[-1], 2, function(x) x[,1]-x[,2])) %>%
      setNames(c("position", apply(combn(names(wide_df[-1]), 2), 2, paste0, collapse = "-")))
    

    输出

      position 1.a-1.b 1.a-2.a 1.a-2.b 1.a-3.a 1.a-3.b 1.b-2.a 1.b-2.b 1.b-3.a 1.b-3.b 2.a-2.b 2.a-3.a 2.a-3.b 2.b-3.a
    1       10   -0.05   -0.03   -0.22    0.04   -0.19    0.02   -0.17    0.09   -0.14   -0.19    0.07   -0.16    0.26
    2       20   -0.02   -0.34   -0.25    0.08   -0.01   -0.32   -0.23    0.10    0.01    0.09    0.42    0.33    0.33
      2.b-3.b 3.a-3.b
    1    0.03   -0.23
    2    0.24   -0.09
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-08-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-19
      • 2015-02-01
      • 2022-11-25
      相关资源
      最近更新 更多