从 tibble (R, dplyr) 中的每一行中减去 1 行
Subtract 1 row from each row in a tibble (R, dplyr)
这应该很简单... dplyr 中的行向操作
#tibble
a=tibble(a=1:4,b=1:4,c=1:4)
#one row tibble to be subtracted from first one
b=tibble(a=5,b=5,c=5)
#well, this won't work
a-b
Error in Ops.data.frame(a, b) :
‘-’ only defined for equally-sized data frames
当然,解决方法是复制 tibble 的行...但并不优雅
#replicating
c=tibble(a=rep(5,4),b=rep(5,4),c=rep(5,4))
#works
a-c
但这不应该与某些行操作一起使用吗?
a %>% rowwise %>% mutate(across(everything(), ~.-b))
没有
# A tibble: 4 × 3
# Rowwise:
a b c
<int> <int> <int>
1 0 0 0
2 0 0 0
3 0 0 0
4 0 0 0
编辑:答案汇编
首先,更清晰地表述问题:
#tibble
a <- tibble(a=1:4,b=1:4,c=1:4)
#one row tibble to be subtracted from first one
b <- tibble(a=5,b=2,c=1)
#objective: turn this into a full-dplyr one-liner
a - b[rep(1,nrow(a)),]
现在,解决方案:
#Gregor's answer below is very clean
a %>% {. - b[rep(1, nrow(.)), ]}
#Full-dplyr is just slightly longer
a %>% {. - slice(b, rep(1,nrow(.)) ) }
#Ronak's answer is most compact
purrr::pmap_dfr(a, ~. - b)
#without the namespace even better:
pmap_dfr(a, ~. - b)
已编辑以反映 OP 的编辑...
我想这就是你想要的:
b=as.numeric(c(5,2,1))
#well, this works
a-b
> a-b
a b c
1 -4 -4 -4
2 -3 -3 -3
3 -2 -2 -2
4 -1 -1 -1
当然
b=as.numeric(tibble(a=5,b=2,c=1))
有效。或者,如果您真的想将 b 保存为其他用途的 tibble...
b=tibble(a=5,b=2,c=1)
a-as.numeric(b)
也可以。请注意错误消息的文本:
“Ops.data.frame(a, b) 中的错误:
‘-’仅为 equally-sized 数据帧定义”告诉你这一点。
如果您想留在 tidyverse
中,您可以使用 pmap_dfr
,这将有助于对多列进行按行操作。
b=tibble(a=5,b=2,c=1)
purrr::pmap_dfr(a, ~. - b)
# a b c
#1 -4 -1 0
#2 -3 0 1
#3 -2 1 2
#4 -1 2 3
在基础 R 中,你可以做到
t(t(a) - unlist(b))
# a b c
#[1,] -4 -1 0
#[2,] -3 0 1
#[3,] -2 1 2
#[4,] -1 2 3
请注意,为了清楚起见,我更改了 b
的值。
通常,使用 long-formatted 数据框可以使这些类型的操作保持一致。这里的技巧是创建一个行 ID,旋转更长,连接,然后旋转更宽。
library(tibble)
#tibble
a <- tibble(a=1:4,b=1:4,c=1:4)
#one row tibble to be subtracted from first one
b <- tibble(a=5,b=5,c=5)
library(tidyr)
library(dplyr)
a_pivot <- a |>
mutate(id = row_number()) |> # create a row ID so we can pivot_wider
pivot_longer(cols = c(everything(), -id), values_to = "values_a")
b_pivot <- b |>
pivot_longer(cols = everything(), values_to = "values_b")
ab_pivot <- left_join(a_pivot, b_pivot, by = c("name")) |>
mutate(values = values_a - values_b) |>
select(id, name, values) |> # remove other columns for the pivot_wider
pivot_wider(names_from = "name", values_from = values) |>
select(-id)
一个dplyr
唯一的解决方案:
library(dplyr)
x = nrow(a)
b <- b %>% slice(rep(1:n(), each =x))
a - b
a b c
1 -4 -4 -4
2 -3 -3 -3
3 -2 -2 -2
4 -1 -1 -1
这应该很简单... dplyr 中的行向操作
#tibble
a=tibble(a=1:4,b=1:4,c=1:4)
#one row tibble to be subtracted from first one
b=tibble(a=5,b=5,c=5)
#well, this won't work
a-b
Error in Ops.data.frame(a, b) :
‘-’ only defined for equally-sized data frames
当然,解决方法是复制 tibble 的行...但并不优雅
#replicating
c=tibble(a=rep(5,4),b=rep(5,4),c=rep(5,4))
#works
a-c
但这不应该与某些行操作一起使用吗?
a %>% rowwise %>% mutate(across(everything(), ~.-b))
没有
# A tibble: 4 × 3
# Rowwise:
a b c
<int> <int> <int>
1 0 0 0
2 0 0 0
3 0 0 0
4 0 0 0
编辑:答案汇编
首先,更清晰地表述问题:
#tibble
a <- tibble(a=1:4,b=1:4,c=1:4)
#one row tibble to be subtracted from first one
b <- tibble(a=5,b=2,c=1)
#objective: turn this into a full-dplyr one-liner
a - b[rep(1,nrow(a)),]
现在,解决方案:
#Gregor's answer below is very clean
a %>% {. - b[rep(1, nrow(.)), ]}
#Full-dplyr is just slightly longer
a %>% {. - slice(b, rep(1,nrow(.)) ) }
#Ronak's answer is most compact
purrr::pmap_dfr(a, ~. - b)
#without the namespace even better:
pmap_dfr(a, ~. - b)
已编辑以反映 OP 的编辑...
我想这就是你想要的:
b=as.numeric(c(5,2,1))
#well, this works
a-b
> a-b
a b c
1 -4 -4 -4
2 -3 -3 -3
3 -2 -2 -2
4 -1 -1 -1
当然
b=as.numeric(tibble(a=5,b=2,c=1))
有效。或者,如果您真的想将 b 保存为其他用途的 tibble...
b=tibble(a=5,b=2,c=1)
a-as.numeric(b)
也可以。请注意错误消息的文本: “Ops.data.frame(a, b) 中的错误: ‘-’仅为 equally-sized 数据帧定义”告诉你这一点。
如果您想留在 tidyverse
中,您可以使用 pmap_dfr
,这将有助于对多列进行按行操作。
b=tibble(a=5,b=2,c=1)
purrr::pmap_dfr(a, ~. - b)
# a b c
#1 -4 -1 0
#2 -3 0 1
#3 -2 1 2
#4 -1 2 3
在基础 R 中,你可以做到
t(t(a) - unlist(b))
# a b c
#[1,] -4 -1 0
#[2,] -3 0 1
#[3,] -2 1 2
#[4,] -1 2 3
请注意,为了清楚起见,我更改了 b
的值。
通常,使用 long-formatted 数据框可以使这些类型的操作保持一致。这里的技巧是创建一个行 ID,旋转更长,连接,然后旋转更宽。
library(tibble)
#tibble
a <- tibble(a=1:4,b=1:4,c=1:4)
#one row tibble to be subtracted from first one
b <- tibble(a=5,b=5,c=5)
library(tidyr)
library(dplyr)
a_pivot <- a |>
mutate(id = row_number()) |> # create a row ID so we can pivot_wider
pivot_longer(cols = c(everything(), -id), values_to = "values_a")
b_pivot <- b |>
pivot_longer(cols = everything(), values_to = "values_b")
ab_pivot <- left_join(a_pivot, b_pivot, by = c("name")) |>
mutate(values = values_a - values_b) |>
select(id, name, values) |> # remove other columns for the pivot_wider
pivot_wider(names_from = "name", values_from = values) |>
select(-id)
一个dplyr
唯一的解决方案:
library(dplyr)
x = nrow(a)
b <- b %>% slice(rep(1:n(), each =x))
a - b
a b c
1 -4 -4 -4
2 -3 -3 -3
3 -2 -2 -2
4 -1 -1 -1