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

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

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

问题

Here is the translated code portion:

  1. 我有一个简单的数据框
  2. df <- data.frame(
  3. col1 = c(1, 2, 3),
  4. col2 = c(4, 5, 6),
  5. col3 = c(7, 8, 9)
  6. )
  7. 我想要一个新的数据框,其中包含每一列与其他列的减法结果,依次计算。我认为这会完成任务
  8. result_df <- data.frame()
  9. # 从所有其他列中减去每一列
  10. for (i in 1:ncol(df)) {
  11. column_diff <- apply(df[, -i], 2, function(x) df[, i] - x)
  12. result_df <- cbind(result_df, column_diff)
  13. }
  14. 但问题是什么?
英文:

I have a simple datafrme

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

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

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

but what is the issue?

答案1

得分: 1

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

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

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

  1. cdiff <- function(i) apply(df[, -i], 2, function(x) df[, i] - x)
  2. newcols <- lapply(1:ncol(df), cdiff)
  3. 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:

  1. 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:

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

答案2

得分: 1

简单

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

  1. library(tidyverse)
  2. d <- data.frame(col1 = 1:3, col2 = 4:6, col3 = 7:9)
  3. seq_along(d) %>% map_dfc(.f = \(x){d[,x] - d[,-x]})
  4. #> col2...1 col3...2 col1...3 col3...4 col1...5 col2...6
  5. #> 1 -3 -6 3 -3 6 3
  6. #> 2 -3 -6 3 -3 6 3
  7. #> 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 参数以控制命名。

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

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

高级

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

  1. seq_along(d) %>%
  2. map(.f = \(x) {
  3. d[, x] - d[,-x] %>%
  4. rename_with(\(y) {paste0(names(d)[x], "-", y)})
  5. }) %>%
  6. list_cbind()
  7. #> col1-col2 col1-col3 col2-col1 col2-col3 col3-col1 col3-col2
  8. #> 1 -3 -6 3 -3 6 3
  9. #> 2 -3 -6 3 -3 6 3
  10. #> 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:

  1. library(tidyverse)
  2. d &lt;- data.frame(col1 = 1:3, col2 = 4:6, col3 = 7:9)
  3. seq_along(d) %&gt;% map_dfc(.f = \(x){d[,x] - d[,-x]})
  4. #&gt; col2...1 col3...2 col1...3 col3...4 col1...5 col2...6
  5. #&gt; 1 -3 -6 3 -3 6 3
  6. #&gt; 2 -3 -6 3 -3 6 3
  7. #&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.

  1. seq_along(d) %&gt;%
  2. map(.f = \(x){d[,x] - d[,-x]}) %&gt;%
  3. list_cbind(name_repair = &quot;minimal&quot;)
  4. #&gt; col2 col3 col1 col3 col1 col2
  5. #&gt; 1 -3 -6 3 -3 6 3
  6. #&gt; 2 -3 -6 3 -3 6 3
  7. #&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().

  1. seq_along(d) %&gt;%
  2. map(.f = \(x) {
  3. d[, x] - d[,-x] %&gt;%
  4. rename_with(\(y) {paste0(names(d)[x], &quot;-&quot;, y)})
  5. }) %&gt;%
  6. list_cbind()
  7. #&gt; col1-col2 col1-col3 col2-col1 col2-col3 col3-col1 col3-col2
  8. #&gt; 1 -3 -6 3 -3 6 3
  9. #&gt; 2 -3 -6 3 -3 6 3
  10. #&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:

  1. library(dplyr)
  2. library(purrr)
  3. cdiff <- function(x) {
  4. df %>%
  5. select(-{{x}}) %>%
  6. transmute(!!paste0("col", x, ".diff") := df[[x]] - .)
  7. }
  8. map_dfc(1:ncol(df), cdiff)
  9. col1.diff.col2 col1.diff.col3 col2.diff.col1 col2.diff.col3 col3.diff.col1 col3.diff.col2
  10. 1 -3 -6 3 -3 6 3
  11. 2 -3 -6 3 -3 6 3
  12. 3 -3 -6 3 -3 6 3
  13. ```"
  14. <details>
  15. <summary>英文:</summary>
  16. 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

  1. </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:

确定