4
$\begingroup$

I have a nested list with 1-D sublists of equal length. I want to subtract another list from each of these sublists.

Task: Subtracting B from each element in A to get the result C.

A = {{5,3,5,7,2},{2,6,4,8,3}}

B = {1,2,1,2,1}

C = {{4,1,4,5,1},{1,4,3,6,2}}

I've used multiple tables to perform this. However, the code takes too long, especially for many nests (columns)*. Is there a faster way?


*In my case, I have many nests as it is time series data. Each nest represents a new column.

$\endgroup$
1
  • $\begingroup$ Yes! Thank you. $\endgroup$
    – reemodels
    Sep 20, 2019 at 8:41

6 Answers 6

7
$\begingroup$
c = Map[Subtract[#, B]&] @ A (* or *)

c =  # - B & /@ A

{{4, 1, 4, 5, 1}, {1, 4, 3, 6, 2}}

Also

A - ConstantArray[B, Length @ A]

{{4, 1, 4, 5, 1}, {1, 4, 3, 6, 2}}

Note: C is a protected system symbol.

$\endgroup$
7
$\begingroup$

In versions 13.1+, you can use Threaded:

A - Threaded[B]
{{4, 1, 4, 5, 1}, {1, 4, 3, 6, 2}}

Threaded:

enter image description here

$\endgroup$
4
$\begingroup$

Using Inner:

A = {{5, 3, 5, 7, 2}, {2, 6, 4, 8, 3}, {1, 2, 3, 4, 5}}
B = {1, 2, 1, 2, 1}

Inner[Subtract, A, B, List]

{{4, 1, 4, 5, 1}, {1, 4, 3, 6, 2}, {0, 0, 2, 2, 4}}

$\endgroup$
3
  • 1
    $\begingroup$ (+1) Also A-{B,B}? $\endgroup$
    – user1066
    Apr 11, 2023 at 6:02
  • 1
    $\begingroup$ Works for the case in the OP. The hidden magic number is the number of times you have to write B though. $\endgroup$
    – Syed
    Apr 11, 2023 at 6:05
  • 1
    $\begingroup$ Maybe, but if A is large and speed is a consideration, Inner will be slow? Transpose[Transpose[A]-B], for example, should be faster? (but +1 anyway!) $\endgroup$
    – user1066
    Apr 11, 2023 at 10:48
4
$\begingroup$

If matrix A is large and speed is a consideration, another possibility is to use a double Transpose

(See this answer by Artes to the question Add a vector to a list of vectors)

A
B
Transpose[Transpose[A]-B]

(* 
{{5, 3, 5, 7, 2}, {2, 6, 4, 8, 3}}
{1, 2, 1, 2, 1}
{{4, 1, 4, 5, 1}, {1, 4, 3, 6, 2}}
*)

And

lstC={{5, 3, 5, 7, 2}, {2, 6, 4, 8, 3}, {1, 2, 3, 4, 5}, {1,10,100,1000,100000}};
lstC
B
Transpose[Transpose[lstC]-B]

(*
{{5, 3, 5, 7, 2}, {2, 6, 4, 8, 3}, {1, 2, 3, 4, 5}, {1, 10, 100, 1000, 100000}}
{1, 2, 1, 2, 1}
{{4, 1, 4, 5, 1}, {1, 4, 3, 6, 2}, {0, 0, 2, 2, 4}, {0, 8, 99, 998, 99999}}
*)

Transpose Entry Shortcut

Artes has also pointed out that Transpose may be entered "very concisely in the Front-End" as Esc tr Esc

$\endgroup$
2
$\begingroup$

Using Nest with the @kglr's idea:

Nest[Map[Subtract[#, B] &], A, 1]

(*{{4, 1, 4, 5, 1}, {1, 4, 3, 6, 2}}*)

Or using FixedPoint with the @kglr's idea:

FixedPoint[Map[Subtract[#, B] &], A, 1]

(*{{4, 1, 4, 5, 1}, {1, 4, 3, 6, 2}}*)

Or using ReplaceAt with the @kglr's idea:

ReplaceAt[{A}, _ -> Map[#1 - B &], 0]

(*{{4, 1, 4, 5, 1}, {1, 4, 3, 6, 2}}*)
$\endgroup$
2
$\begingroup$
a = {{5, 3, 5, 7, 2}, {2, 6, 4, 8, 3}};

b = {1, 2, 1, 2, 1};

Using Function

(x |-> x - b) /@ a

Using BlockMap and Riffle

BlockMap[Apply @ Subtract, Riffle[a, {b}, {2, -1, 2}], 2]

Using Subtract and Join

Subtract @@@ Map[Join[{#}, {b}] &, a]

All return

{{4, 1, 4, 5, 1}, {1, 4, 3, 6, 2}}

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.