4
$\begingroup$

I have data in the the form of a table, whose one column is the following

{1.94238, 1.94361, 4.72888},
 {1.94477, 1.94938, 4.71431},
 {1.94893, 1.95817, 4.69017},
 {1.9551, 1.96907, 4.65627},
 {1.9637, 1.98115, 4.61168},
 {1.97539, 1.99357, 4.55427},
 {1.99141, 2.00535, 4.48002},
          {4.38177},
          {4.24668},
 {2.04454, 2.07149, 4.05151},
 {2.05173, 2.13016, 3.75524},
 {2.05838, 2.23059, 3.29844},
           {2.0636},
           {2.0672},
           {2.06916},
           {2.06951}

I want to pad the single elements from left and right with Null and bring the above into the following form

 {1.94238, 1.94361, 4.72888},
 {1.94477, 1.94938, 4.71431},
 {1.94893, 1.95817, 4.69017},
 {1.9551, 1.96907, 4.65627},
 {1.9637, 1.98115, 4.61168},
 {1.97539, 1.99357, 4.55427},
 {1.99141, 2.00535, 4.48002},
       {Null, Null, 4.38177},
       {Null, Null, 4.24668},
 {2.04454, 2.07149, 4.05151},
 {2.05173, 2.13016, 3.75524},
 {2.05838, 2.23059, 3.29844},
 {2.0636, Null, Null},
 {2.0672, Null, Null},
 {2.06916, Null, Null},
 {2.06951, Null, Null}
$\endgroup$
  • $\begingroup$ PadLeft[list, Automatic, Null] pads on the left with Null. $\endgroup$ – kglr Aug 30 at 16:50
  • $\begingroup$ and PadRight[list, Automatic, Null] pads on the right. you need to provide the row number ( or the rule) to switch between left and right padding. $\endgroup$ – kglr Aug 30 at 16:51
  • 1
    $\begingroup$ @kglr Thanks, just counting from 1, from the top. For instance, if this varies from column to column, is there then a generic rule to do such right and left padding? I mean if the row number containing the list to be padded varies? $\endgroup$ – AtoZ Aug 30 at 16:56
8
$\begingroup$

Update: We can define a conditional padding function conditionalPad[test] that pads on left or right depending on whether the two-argument function test evaluates to True. The two arguments of the input function test are the value and the index of a row element.

ClearAll[conditionalPad]
conditionalPad[test_] := Module[{l = Max[Length /@ #]}, 
    MapIndexed[If[test[#, #2[[1]]], 
       PadLeft[#, l, Null], 
       PadLeft[#, -l, Null]] &, #]] &;

With the test function

t1 = #2 <= 10 &;

conditionalPad[t1] @ list replicates the first example in the original answer and Lee's example.

conditionalPad[t2] @ list where

t2 = MemberQ[leftpaddedrows, #2] &;

gives the same output as the second example.

With the test function

t3 = OddQ[#2] &;

we replicate sakra's example.

The test function True& pads on the left (and False& pads on the right) unconditionally.

Additional examples where the test function depends only on a value of the row (t4), on both a value and index (t5) , on neither (t6) are

t4 = #[[1]] <= 3 &;
t5  = Abs[#[[1]] - #2] < 5 &
t6 = (Norm[Last /@ list] <= 3) &;

Original answer:

list = {{1.94238, 1.94361, 4.72888}, {1.94477, 1.94938, 
    4.71431}, {1.94893, 1.95817, 4.69017}, {1.9551, 1.96907, 
    4.65627}, {1.9637, 1.98115, 4.61168}, {1.97539, 1.99357, 
    4.55427}, {1.99141, 2.00535, 4.48002}, {4.38177}, {4.24668}, {2.04454, 2.07149, 
    4.05151}, {2.05173, 2.13016, 3.75524}, {2.05838, 2.23059, 
    3.29844}, {2.0636}, {2.0672}, {2.06916}, {2.06951}};

You can use PadLeft and PadRight:

list1 = PadLeft[list, Automatic, Null];

TeXForm @ MatrixForm[list1]

$\tiny \left( \begin{array}{ccc} 1.94238 & 1.94361 & 4.72888 \\ 1.94477 & 1.94938 & 4.71431 \\ 1.94893 & 1.95817 & 4.69017 \\ 1.9551 & 1.96907 & 4.65627 \\ 1.9637 & 1.98115 & 4.61168 \\ 1.97539 & 1.99357 & 4.55427 \\ 1.99141 & 2.00535 & 4.48002 \\ \text{Null} & \text{Null} & 4.38177 \\ \text{Null} & \text{Null} & 4.24668 \\ 2.04454 & 2.07149 & 4.05151 \\ 2.05173 & 2.13016 & 3.75524 \\ 2.05838 & 2.23059 & 3.29844 \\ \text{Null} & \text{Null} & 2.0636 \\ \text{Null} & \text{Null} & 2.0672 \\ \text{Null} & \text{Null} & 2.06916 \\ \text{Null} & \text{Null} & 2.06951 \\ \end{array} \right)$

Tow switch from left padding to right padding after row t:

t = 10;
list2 = list;
list2[[;; t]] = PadLeft[list2[[;; t]], Automatic, Null];
list2[[t + 1 ;;]] = PadRight[list2[[t + 1 ;;]], Automatic, Null];

TeXForm @ MatrixForm[list2]

$\tiny \left( \begin{array}{ccc} 1.94238 & 1.94361 & 4.72888 \\ 1.94477 & 1.94938 & 4.71431 \\ 1.94893 & 1.95817 & 4.69017 \\ 1.9551 & 1.96907 & 4.65627 \\ 1.9637 & 1.98115 & 4.61168 \\ 1.97539 & 1.99357 & 4.55427 \\ 1.99141 & 2.00535 & 4.48002 \\ \text{Null} & \text{Null} & 4.38177 \\ \text{Null} & \text{Null} & 4.24668 \\ 2.04454 & 2.07149 & 4.05151 \\ 2.05173 & 2.13016 & 3.75524 \\ 2.05838 & 2.23059 & 3.29844 \\ 2.0636 & \text{Null} & \text{Null} \\ 2.0672 & \text{Null} & \text{Null} \\ 2.06916 & \text{Null} & \text{Null} \\ 2.06951 & \text{Null} & \text{Null} \\ \end{array} \right)$

To pad left at rows in the list leftpaddedrows and right at rows in the list rightpaddedrows:

SeedRandom[1]
leftpaddedrows = RandomSample[Range@Length@list, 10];
rightpaddedrows = Complement[Range[Length@list], leftpaddedrows];

list3 = list;
list3[[leftpaddedrows]] = PadLeft[list3[[leftpaddedrows]], Automatic, Null];
list3[[rightpaddedrows]] = PadRight[list3[[rightpaddedrows]], Automatic, Null];

TeXForm @ MatrixForm[list3]

$\tiny \left( \begin{array}{ccc} 1.94238 & 1.94361 & 4.72888 \\ 1.94477 & 1.94938 & 4.71431 \\ 1.94893 & 1.95817 & 4.69017 \\ 1.9551 & 1.96907 & 4.65627 \\ 1.9637 & 1.98115 & 4.61168 \\ 1.97539 & 1.99357 & 4.55427 \\ 1.99141 & 2.00535 & 4.48002 \\ \text{Null} & \text{Null} & 4.38177 \\ \text{Null} & \text{Null} & 4.24668 \\ 2.04454 & 2.07149 & 4.05151 \\ 2.05173 & 2.13016 & 3.75524 \\ 2.05838 & 2.23059 & 3.29844 \\ \text{Null} & \text{Null} & 2.0636 \\ \text{Null} & \text{Null} & 2.0672 \\ 2.06916 & \text{Null} & \text{Null} \\ 2.06951 & \text{Null} & \text{Null} \\ \end{array} \right)$

$\endgroup$
6
$\begingroup$

Another approach if you want to left pad the first n one-element lists and right pad the rest is:

lst = {{1.94238, 1.94361, 4.72888}, {1.94477, 1.94938, 
   4.71431}, {1.94893, 1.95817, 4.69017}, {1.9551, 1.96907, 
   4.65627}, {1.9637, 1.98115, 4.61168}, {1.97539, 1.99357, 
   4.55427}, {1.99141, 2.00535, 
   4.48002}, {4.38177}, {4.24668}, {2.04454, 2.07149, 
   4.05151}, {2.05173, 2.13016, 3.75524}, {2.05838, 2.23059, 
   3.29844}, {2.0636}, {2.0672}, {2.06916}, {2.06951}}

padLen = Length /@ lst // Max;

Followed by calls to SequenceReplace:

nlst = SequenceReplace[lst, {{x_}} :> PadLeft[{x}, padLen, Null], 2];
alst = SequenceReplace[nlst, {{x_}} :> PadRight[{x}, padLen, Null]] // TableForm

enter image description here

$\endgroup$
3
$\begingroup$

Use MapThread to specify a padding plan for each row, i.e.:

paddingPlan = {3, 3, 3, 3, 3, 3, 3, 3, 3, 3, -3, -3, -3, -3, -3, -3};
MapThread[
   PadLeft[#1, #2, Null] &, 
   {list, paddingPlan}
]

The padding plan can also be generated programmatically. E.g., use alternating padding values for rows with an odd or even row index:

paddingPlan = Array[If[OddQ[#], 3, -3] &, Length@list]
$\endgroup$
1
$\begingroup$
list /.{{x_/;IntegerPart[x]==4}:> {Null,Null,x}, {x_/;IntegerPart[x]==2}:> {x,Null,Null}}


% // MatrixForm

enter image description here

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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