如何将数据框每一列的值从所有其他列中减去?

huangapple go评论72阅读模式
英文:

How can I subtract values of each column of my dataframe from all other columns?

问题

Here is the translated code portion:

我有一个简单的数据框

    df <- data.frame(
      col1 = c(1, 2, 3),
      col2 = c(4, 5, 6),
      col3 = c(7, 8, 9)
    )

我想要一个新的数据框,其中包含每一列与其他列的减法结果,依次计算。我认为这会完成任务

    result_df <- data.frame()

    # 从所有其他列中减去每一列
    for (i in 1:ncol(df)) {
      column_diff <- apply(df[, -i], 2, function(x) df[, i] - x)
      result_df <- cbind(result_df, column_diff)
    }

但问题是什么?
英文:

I have a simple datafrme

df &lt;- data.frame(
  col1 = c(1, 2, 3),
  col2 = c(4, 5, 6),
  col3 = c(7, 8, 9)
)

And I want to have a new dataframe that will contain the results of subtraction of each column from all others, one by one. I assume that will do the job

result_df &lt;- data.frame()

# Subtract each column from all the other columns
for (i in 1:ncol(df)) {
  column_diff &lt;- apply(df[, -i], 2, function(x) df[, i] - x)
  result_df &lt;- cbind(result_df, column_diff)
}

but what is the issue?

答案1

得分: 1

如果您想要使用 cbind(),您需要将具有相同列数的元素组合在一起。我认为您可以像这样设置 result_df

result_df <- data.frame(matrix(nrow=3, ncol=0))

或者创建一个列差异的列表,然后将它们组合起来可能更好:

cdiff <- function(i) apply(df[, -i], 2, function(x) df[, i] - x)
newcols <- lapply(1:ncol(df), cdiff)
data.frame(newcols)
英文:

If you want to cbind() you need to combine elements with the same number of columns. I think you could set up result_df like this:

result_df &lt;- data.frame(matrix(nrow=3, ncol = 0))

Or it might be better to create a list of column-differences, then combine them:

cdiff &lt;- function(i) apply(df[, -i], 2, function(x) df[, i] - x)
newcols &lt;- lapply(1:ncol(df), cdiff)
data.frame(newcols)

答案2

得分: 1

简单

在 {tidyverse} 中,可以使用 purrr::map_dfc() 来执行类似于您所使用的函数:

library(tidyverse)

d <- data.frame(col1 = 1:3, col2 = 4:6, col3 = 7:9)

seq_along(d) %>% map_dfc(.f = \(x){d[,x] - d[,-x]})

#>   col2...1 col3...2 col1...3 col3...4 col1...5 col2...6
#> 1       -3       -6        3       -3        6        3
#> 2       -3       -6        3       -3        6        3
#> 3       -3       -6        3       -3        6        3

创建于 2023-06-04,使用 reprex v2.0.2

更新

purrr::map_dfc() 在 {purrr} 1.0.0 中已弃用,现在可以使用 map()list_cbind() 来进行正确的操作,这允许您指定 names_repair 参数以控制命名。

seq_along(d) %>%
  map(.f = \(x){d[,x] - d[,-x]}) %>%
  list_cbind(name_repair = "minimal")
#>   col2 col3 col1 col3 col1 col2
#> 1   -3   -6    3   -3    6    3
#> 2   -3   -6    3   -3    6    3
#> 3   -3   -6    3   -3    6    3

创建于 2023-06-05,使用 reprex v2.0.2

高级

如果您想要更高级的操作,并且希望新列反映生成它们的计算过程,您可以使用 dplyr::rename_with()


seq_along(d) %>%
  map(.f = \(x) {
    d[, x] - d[,-x] %>%
      rename_with(\(y) {paste0(names(d)[x], "-", y)})
    }) %>%
  list_cbind()
#>   col1-col2 col1-col3 col2-col1 col2-col3 col3-col1 col3-col2
#> 1        -3        -6         3        -3         6         3
#> 2        -3        -6         3        -3         6         3
#> 3        -3        -6         3        -3         6         3

创建于 2023-06-05,使用 reprex v2.0.2

英文:

Simple

In the {tidyverse} this can be done with purrr::map_dfc() using a function similar to what you had:

library(tidyverse)

d &lt;- data.frame(col1 = 1:3, col2 = 4:6, col3 = 7:9)

seq_along(d) %&gt;% map_dfc(.f = \(x){d[,x] - d[,-x]})

#&gt;   col2...1 col3...2 col1...3 col3...4 col1...5 col2...6
#&gt; 1       -3       -6        3       -3        6        3
#&gt; 2       -3       -6        3       -3        6        3
#&gt; 3       -3       -6        3       -3        6        3

<sup>Created on 2023-06-04 with reprex v2.0.2</sup>

Updated

purrr::map_dfc() was deprecated in {purrr} 1.0.0 so it would properly be done now using map() with list_cbind() which enables one to specify the names_repair argument to control the naming.

seq_along(d) %&gt;% 
  map(.f = \(x){d[,x] - d[,-x]}) %&gt;% 
  list_cbind(name_repair = &quot;minimal&quot;)
#&gt;   col2 col3 col1 col3 col1 col2
#&gt; 1   -3   -6    3   -3    6    3
#&gt; 2   -3   -6    3   -3    6    3
#&gt; 3   -3   -6    3   -3    6    3

<sup>Created on 2023-06-05 with reprex v2.0.2</sup>

Fancy

If you you want to get fancy and have the new columns reflect the calculation that produced them, you could use dplyr::rename_with().


seq_along(d) %&gt;%
  map(.f = \(x) {
    d[, x] - d[,-x] %&gt;% 
      rename_with(\(y) {paste0(names(d)[x], &quot;-&quot;, y)})
    }) %&gt;%
  list_cbind()
#&gt;   col1-col2 col1-col3 col2-col1 col2-col3 col3-col1 col3-col2
#&gt; 1        -3        -6         3        -3         6         3
#&gt; 2        -3        -6         3        -3         6         3
#&gt; 3        -3        -6         3        -3         6         3

<sup>Created on 2023-06-05 with reprex v2.0.2</sup>

答案3

得分: 0

以下是您要翻译的内容:

"While I prefer the solution by @Ben Bolker, here is a fun one:

library(dplyr)
library(purrr)

cdiff <- function(x) {
  df %>%
    select(-{{x}}) %>%
    transmute(!!paste0("col", x, ".diff") := df[[x]] - .)
}

map_dfc(1:ncol(df), cdiff)


col1.diff.col2 col1.diff.col3 col2.diff.col1 col2.diff.col3 col3.diff.col1 col3.diff.col2
1             -3             -6              3             -3              6              3
2             -3             -6              3             -3              6              3
3             -3             -6              3             -3              6              3
```"

<details>
<summary>英文:</summary>

While I prefer the solution by @Ben Bolker, here is a fun one: 

library(dplyr)
library(purrr)

cdiff <- function(x) {
df %>%
select(-{{x}}) %>%
transmute(!!paste0("col", x, ".diff") := df[[x]] - .)
}

map_dfc(1:ncol(df), cdiff)

col1.diff.col2 col1.diff.col3 col2.diff.col1 col2.diff.col3 col3.diff.col1 col3.diff.col2
1 -3 -6 3 -3 6 3
2 -3 -6 3 -3 6 3
3 -3 -6 3 -3 6 3


</details>



huangapple
  • 本文由 发表于 2023年6月5日 02:04:33
  • 转载请务必保留本文链接:https://go.coder-hub.com/76401780.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定