2
$\begingroup$

I want to find all non zero elements of a table and I want to create a list that contains the name of the table the element was removed from, the position of the element, and the value of the element.

Then to the generated list I would like to apply a replacment rule to the row and the column.

rule = {1 -> "a", 2 -> "b", 3 -> "c"}

{ {tablename, row, col, value} }

For example I have tried

dataTable1 = {{1,0,0}, {0,1,0}, {0,0,-1}} 

Position[Abs[dataTable1], # > 0 &]

but I am unable to get get the position. I would like the final out put to be

 { {"dataTable1", 1,1,1}, {"dataTable1", 2,2,1}, {"dataTable1", 3,3,-1} }

If we apply the replacment.

  { {"dataTable1", 1,1,1}, {"dataTable1", 2,2,1}, {"dataTable1", 3,3,-1} } /. rule 

Then the output should be

 { {"dataTable1", "a","a",1}, {"dataTable1", "b","b",1}, {"dataTable1", "c","c",-1} }
$\endgroup$
3
  • 3
    $\begingroup$ SparseArray[dataTable1]["NonzeroPositions"] gives you your {{1, 1}, {2, 2}, {3, 3}} and "NonzeroValues" gives {1, 1, -1}. It is not quite clear from your question how the tables are organized to be able to extract their names, but I suppose you can figure the rest of it out by yourself. $\endgroup$ Apr 27, 2014 at 3:54
  • $\begingroup$ In this case their names are just the name of variable. IE: datatable1 is named "datatable1" $\endgroup$
    – olliepower
    Apr 27, 2014 at 3:58
  • $\begingroup$ @olliepower: lol, typing as you commented... same idea $\endgroup$
    – ciao
    Apr 27, 2014 at 4:06

2 Answers 2

10
$\begingroup$
info[tbl_] := With[{s = SparseArray[tbl]},
  ArrayPad[Append @@@ Transpose[{s["NonzeroPositions"], s["NonzeroValues"]}], 
          {0, {1, 0}}, ToString@Unevaluated@tbl]]

SetAttributes[info, HoldFirst]

result=info[dataTable1]

(* {{"dataTable1", 1, 1, 1}, {"dataTable1", 2, 2, 1}, {"dataTable1", 3, 3, -1}} *)

As to the second part of your query, assume the result from the info function is in a symbol named result, then using your example rule list,

MapAt[(# /. rule) &, result, {All, 2 ;; 3}]

(* 
 {{"dataTable1", "a", "a", 1}, {"dataTable1", "b", "b", 1},{"dataTable1", "c", "c", -1}} 
*)
$\endgroup$
6
  • $\begingroup$ this worked. I have one other question. What if I want to apply a replacemnt rule to only the positions after the list has been constructed. For example info[dataTables1] /. rules Where rules should only apply to the second and third elements of each sublist. $\endgroup$
    – olliepower
    Apr 27, 2014 at 4:16
  • $\begingroup$ @olliepower: Need to clarify what you mean, and to where (replace things in the generated list, the original array?). Perhaps append to your OP. $\endgroup$
    – ciao
    Apr 27, 2014 at 4:20
  • $\begingroup$ I have appended to my OP. Thank you once again. $\endgroup$
    – olliepower
    Apr 27, 2014 at 5:26
  • $\begingroup$ @olliepower: appended answer $\endgroup$
    – ciao
    Apr 27, 2014 at 7:05
  • $\begingroup$ Where is "NonzeroPositions" and "NonzeroValues" documented? $\endgroup$
    – Sander
    Mar 1, 2019 at 4:26
1
$\begingroup$

Is it what you want?

SetAttributes[getPos, HoldFirst];
getPos[t_Symbol] := 
 Module[{pos = Position[Abs[t], _?Positive]}, 
  Join[ConstantArray[{ToString[Unevaluated@t]}, Length[pos]], pos, 
   List /@ Extract[t, pos], 2]]

getPos[dataTable1]
{{"dataTable1", 1, 1, 1}, {"dataTable1", 2, 2, 1}, {"dataTable1", 3, 3, -1}}
$\endgroup$
3
  • $\begingroup$ The only problem with this code is if a row of the table contains all zeros. then I get {{"dataTable1"}}. I would not like to have those in the output. $\endgroup$
    – olliepower
    Apr 27, 2014 at 4:05
  • $\begingroup$ I have updated the answer. Please check new version. $\endgroup$ Apr 27, 2014 at 8:24
  • $\begingroup$ @AlexeyPopkov please take a look at chat $\endgroup$
    – Kuba
    Apr 27, 2014 at 8:37

Your Answer

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

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