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$ Commented Apr 27, 2014 at 3:54
  • $\begingroup$ In this case their names are just the name of variable. IE: datatable1 is named "datatable1" $\endgroup$ Commented Apr 27, 2014 at 3:58
  • $\begingroup$ @olliepower: lol, typing as you commented... same idea $\endgroup$ Commented 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$ Commented 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$ Commented Apr 27, 2014 at 4:20
  • $\begingroup$ I have appended to my OP. Thank you once again. $\endgroup$ Commented Apr 27, 2014 at 5:26
  • $\begingroup$ @olliepower: appended answer $\endgroup$ Commented Apr 27, 2014 at 7:05
  • $\begingroup$ Where is "NonzeroPositions" and "NonzeroValues" documented? $\endgroup$ Commented 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$ Commented Apr 27, 2014 at 4:05
  • $\begingroup$ I have updated the answer. Please check new version. $\endgroup$ Commented Apr 27, 2014 at 8:24
  • $\begingroup$ @AlexeyPopkov please take a look at chat $\endgroup$ Commented Apr 27, 2014 at 8:37

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.