1
$\begingroup$

When importing tabular data as Import["URL","Data"], it is often the case that Mathematica will skip returning values for tables in which an entry in the table is blank. For example, in importing some election results from "https://www.presidency.ucsb.edu/statistics/elections/2020", after suitably editing using part and flatten the table to only include relevant data of election results by state, it can be seen that electoral votes are always being imported as type Integer, whereas all other entries are of type String. Thus, even though this creates 56 x 9 matrix, the values in the columns do not coincide by type as desired.

Taking the data for the first 5 states in the list for brevity in this example, the data look like this.

byStatePresidentialVotesData2020 = {{"Alabama", "2,323,282", "849,624", "36.57%", "1,441,170", "62.03%", 
  9, "32,488", "1.40%"}, {"Alaska", "359,530", "153,778", "42.77%", 
  "189,951", "52.83%", 3, "15,801", "4.39%"}, {"Arizona", "3,387,326",
   "1,672,143", "49.36%", 11, "1,661,686", "49.06%", "53,497", 
  "1.58%"}, {"Arkansas", "1,219,069", "423,932", "34.78%", "760,647", 
  "62.40%", 6, "34,490", "2.83%"}, {"California", "17,500,881", 
  "11,110,250", "63.48%", 55, "6,006,429", "34.32%", "384,202", 
  "2.20%"}}

Consequently, I need to add an additional column conditionally either at position 5 or 8 depending on where electoral votes have been left blank in the data as imported.

With column headers (modified to avoid redundant key names) as:

 headers = {"STATE", "TOTAL VOTES", "Votes D", "% D", "EV D", "Votes R", "% R", "EV R", "Votes Others", "% Others"}

this would then permit an association of associations to be built using AssociationThread, for 10 rather than 9 columns, but with appropriate headers suitably aligned.

Because electoral votes are always given as of type Integer, I need to insert a 0 (Integer Zero) into column 5 for those rows for which column 5 is a String, since the entry of the column after a blank column will be of type String rather than Integer and insert a 0 (Integer 0_ at position 8 with a 0 (Integer Zero) for which column 5 is an Integer.

To do this I created the following conditional expression:

If[IntegerQ[Head[byStatePresidentialVotesdData2020[[#, 5]]]], 
   Insert[byStatePresidentialVotesdData2020[[#]], 0, 8], 
   Insert[byStatePresidentialVotesdData2020[[#]], 0, 5]] & /@ 
 Range[Length[byStatePresidentialVotesData2020]]

Unfortunately, rather than inserting columns conditionally, it always inserts a 0 in column 5 even for the rows for "Arizona" and "California", where a zero should have been entered in column 8 instead, even though the Head for the 5th entry in these lists are of type "Integer".

In[221]:= Head[byStatePresidentialVotesData2020[[#, 5]]] & /@ Range[5]

Out[221]= {String, String, Integer, String, Integer}

Can anyone explain why this code fails and how it might be modified to appropriately do the conditional insert as intended?

$\endgroup$
1
  • $\begingroup$ Trying to understand it: How about (If[Head[Part[#, 5]] === String, Insert[#, 0, 5], If[Head[Part[#, 5]] === Integer, Insert[#, 0, 8], #]] & /@ byStatePresidentialVotesData2020 ) // TableForm ? $\endgroup$
    – Syed
    Feb 12, 2023 at 18:43

2 Answers 2

2
$\begingroup$

I will convert my comment into an answer.

byStatePresidentialVotesData2020 = {{"Alabama", "2,323,282", 
   "849,624", "36.57%", "1,441,170", "62.03%", 9, "32,488", 
   "1.40%"}, {"Alaska", "359,530", "153,778", "42.77%", "189,951", 
   "52.83%", 3, "15,801", "4.39%"}, {"Arizona", "3,387,326", 
   "1,672,143", "49.36%", 11, "1,661,686", "49.06%", "53,497", 
   "1.58%"}, {"Arkansas", "1,219,069", "423,932", "34.78%", "760,647",
    "62.40%", 6, "34,490", "2.83%"}, {"California", "17,500,881", 
   "11,110,250", "63.48%", 55, "6,006,429", "34.32%", "384,202", 
   "2.20%"}};

headers = {"STATE", "TOTAL VOTES", "Votes D", "% D", "EV D", 
  "Votes R", "% R", "EV R", "Votes Others", "% Others"};

    (estats = 
       If[Head[Part[#, 5]] === String, Insert[#, 0, 5], 
          If[Head[Part[#, 5]] === Integer, Insert[#, 0, 8], #]] & /@ 
        byStatePresidentialVotesData2020 ) // TableForm

Prepend[estats, headers] //
 Grid[#
   , Alignment -> {{Left, {Center}}, Center}
   , Frame -> All
   , Background -> {{None, None}, {Cyan, White}}
   , Spacings -> {1, 1}
   ] &

enter image description here

$\endgroup$
1
  • 1
    $\begingroup$ Very complete answer. The additional explanation clearly worked through the problem in an understandable way. Now straightforward to convert this to a dataset. Sorry for the delay in responding. A hand injury has limited my keyboard time. $\endgroup$ Jun 19, 2023 at 3:34
2
$\begingroup$

To make things more readable, I would define a function, that takes one row, makes the necessary replacement and returns the result. Then this function can be mapped (for short:/@) onto your data:

f[d0_] :=  Module[{d = d0}, Switch[Head[d[[5]]], String, d = Insert[d, 0, 5], Integer, d = Insert[d, 0, 8]]; d];

result = f /@ byStatePresidentialVotesData2020;
result // TableForm

enter image description here

$\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.