5
$\begingroup$

I have a file with data given in this manner:

{1.30859, 0}
{1.81061, 0}
{9.37376, 0}
{0.341339, 0}
{0.39494, 0}
{1.16172, 0}
{0.139555, 0}
{0.583382, 0}
{15.8124, 0}

How do I import only the first column?

A naive combination of Import[file,"Table"], Flatten and Transpose gives an error.

$\endgroup$
9
$\begingroup$

The short answer is that the following will work to import your file format as an array of numbers, which I think is your intention:

Import[filename, {"Table", "Data", All, 1},"FieldSeparators" -> {"{", ",", "}"}]

this uses the Import features to determine the field separaters to handle the braces and comma in your file content and the data elements to extract just the first column.

An alternative which in this case looks a bit simpler is this:

ToExpression[Import[filename,"List"]][[All,1]]

Note that this will work just for this specific input format (where every line for itself is a valid Mathematica InputForm expression). Why it works in this case needs some explanation:

Choosing Import Format

As this is a text like format you have to give Mathematica some hints about how to interpret what it is reading. You can do that by choosing a suitable import format and additional options for the specific import format as in the first example. If the file extension is ".txt" the default import format will be "Text" and the whole content is interpreted as a single multiline string. Unfortunately with default settings Mathematica will not show "string characters" in output so it is difficult to see what the returned data really is. I usually check that using InputForm or FullForm on the data which will more clearly show what actually is imported:

Import[filename,"Text"]//InputForm

You could then work with that string and transform it to a valid Mathematica expression and convert that to an array of numbers using ToExpression, e.g.:

ToExpression[StringJoin["{", 
  StringReplace[Import[filename, "Text"], "\n" -> ","], "}"]]

Using "Table" as format as you did will by default import every line as a row and separate columns by whitespace, which will in your case produce an array of strings where the entries are not valid Mathematica InputForm expressions. Thus you again need extra string manipulation before you can transform them into numbers (see the other answers for examples). Again you can use InputForm to check what Import really returns in that case. By using the options documented for the "Table" import format you can make Import with format "Table" work as intended as shown in the first example.

Using "List" as format will import every line as a string which is handy in this case as every line is a valid Mathematica InputForm string which can be transformed directly with ToExpression without extra string manipulation.

Working with lists in Mathematica

Once it is clear that Import[filename,"List"] returns a list of strings it might come as a surprise that one can directly feed that to ToExpression, but looking at its documentation will show that it not only works for a single string but also for a list of strings because it has the attribute Listable (which you can check with Attributes[ToExpression]). This is why we can use ToExpression directly on the output of Import, otherwise we would have to use something like:

 ToExpression /@ Import[filename,"List"]

Extracting first column only

istead of transposing you can directly use Part to extract the first column. Using the All argument is not only elegant but also a very efficient way to extract columns (this of course also works at deeper levels). You of course also could use the newer Span syntax (data[[;;,1]]), but I find the All version easier to read when it applies...

Notes about performance

if your file is huge and performance matters there are two possible improvements:

Using ReadList[filename,"String"] might be considerably faster as it avoids some of the Import overhead (haven't checked how much difference that make in newer versions for import format "List").

If the file is so large that memory usage becomes an issue, using ReadLists third argument you could import in batches of rows and avoid to have to read the whole file into memory in one go. That will then be more memory efficient but slower than reading everything at once. This will only be worth the effort for really huge files, though. You can find other questions on this site with examples about how to do that.

$\endgroup$
0
$\begingroup$

I don't think this is the most elegant solution possible, but there you go:

StringDrop[Import[file, {"Data", All, 1}], 1] // ToExpression
$\endgroup$

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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