7
$\begingroup$

I have a .txt file that looks like this (direct copy from the file):

8.1376   7.2490    6.4005                   3.3893e-06 5.4310e-06 1.7980e-05 1.5303e-05 
11.2834  10.1948   8.1657   32.256   68.032 3.2509e-06 3.9237e-06 8.0432e-06 5.3961e-06 
1.5350   1.1260    0.8500                   6.6665e-07 6.8028e-07 1.9302e-06 2.4867e-06 
0.9850   0.6920    0.2360    0.192    0.768 3.3890e-09 9.8610e-09 4.6064e-08 1.3044e-07 
1.5820   1.1040    0.9130   35.712   67.840 3.2341e-07 3.7886e-07 2.4787e-06 2.9939e-06

I'm interested in the 5th column, in which there are some missing data in some rows. When I just

Import["file.txt", "Table"]

MMA does not see the empty positions, so e.g. the first row has 7 elements, and the 5th becomes 5.4310e-06, which is not what I want.

How can I import the data with proper structure, and extract the desired column?

$\endgroup$

2 Answers 2

6
$\begingroup$
str = Import["file.txt", "Data"];
mat = StringSplit[
             StringReplace[str, {"         " -> " {}", "e" -> "*^"}], 
             WhitespaceCharacter ..
       ] // ToExpression;
mat// MatrixForm

enter image description here

$\endgroup$
3
  • $\begingroup$ The "Data" import format is undocumented, not listed in $ImportFormats. The documented (and probably faster) way to do the same is to use ReadList["test.txt", String]. $\endgroup$ Jun 11, 2019 at 17:20
  • $\begingroup$ Interesting! Thanks for the information. $\endgroup$ Jun 11, 2019 at 17:30
  • 1
    $\begingroup$ @AlexeyPopkov "Data" is not a format, if you do Import["foo", "Data"] it is the "Data" element from FileFormat["foo"] $\endgroup$ Jun 14, 2019 at 17:47
4
$\begingroup$

From your example it seems that the stringlength of a number can't be more than 10, so any number consists from 1 to 10 characters (digits, "e" character and the dot "."). Existing numbers can be separated by from one to 10 whitespaces on one line. And the last number can have no whitespace at the end. So we need to preprocess:

str="8.1376   7.2490    6.4005                   3.3893e-06 5.4310e-06 1.7980e-05 1.5303e-05 
11.2834  10.1948   8.1657   32.256   68.032 3.2509e-06 3.9237e-06 8.0432e-06 5.3961e-06 
1.5350   1.1260    0.8500                   6.6665e-07 6.8028e-07 1.9302e-06 2.4867e-06 
0.9850   0.6920    0.2360    0.192    0.768 3.3890e-09 9.8610e-09 4.6064e-08 1.3044e-07 
1.5820   1.1040    0.9130   35.712   67.840 3.2341e-07 3.7886e-07 2.4787e-06 2.9939e-06";

lines=StringSplit[StringReplace[str,{EndOfLine->" ","e"->"*^"}],"\r\n"|"\n"];
matrixOfStrings=StringCases[lines,Repeated[Except[" "],{0,11}]~~Repeated[" ",{1,9}]];
matrix=ToExpression[matrixOfStrings,InputForm];
%//TableForm

screenshot


UPDATE

Another method which allows the columns to have arbitrary width:

str = ReadList["test.txt", String];

Transpose[Transpose[
   PadRight[Characters[str], Automatic, " "]] /. {c : {" " ..} :> Table["\t", Length[c]]
    , "e" -> "*^"}]
ToExpression[StringJoin /@ DeleteCases[SplitBy[#, # === "\t" &], {"\t" ..}] & /@ %]
MatrixForm@%

(output is the same)

$\endgroup$
3
  • $\begingroup$ And how to do it from a file? I.e., how to Import["file.txt"] to obtain your str? $\endgroup$
    – corey979
    Jun 11, 2019 at 16:49
  • $\begingroup$ @corey Use str=Import["file.txt","String"]. Note that on Windows in my code you may be should replace "\n" with "\r\n". $\endgroup$ Jun 11, 2019 at 16:51
  • $\begingroup$ @corey979 I've updated the answer so it should work both under Windows and Linux. $\endgroup$ Jun 11, 2019 at 16:56

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.