Part 4

Employing Advanced MATLAB Techniques

IN THIS PART …

Importing and exporting data from various sources

Presenting data as reports

Outputting data in printed form

Detecting and handling errors

Chapter 16

Importing and Exporting Data

IN THIS CHAPTER

check Obtaining data from other sources

check Outputting data to other recipients

check Interacting with image data

An application isn’t of much use if it can’t interact with data — in the case of MATLAB, the formulas, scripts, Live Scripts, functions, Live Functions, and plots that you create interact with variables. In fact, even applications that you might think have nothing to do with data manage quite a lot of it. For example, you might be tempted to think that games don’t work with data, but even the lowliest Solitaire game saves statistics, which means that it interacts with data. So you can easily see that most applications interact with at least their own data.

Larger, more complex applications, such as MATLAB, also need some method of interacting with data from other applications. For example, you may need to use Excel data from a colleague to perform a calculation. If MATLAB didn’t provide a means to access that data, to import it into MATLAB, you couldn’t use it to perform the calculation.

After you complete the calculation, you may need to send it back to your colleague, but the only application available at the other site is Excel. Now you must export the data from MATLAB into an Excel file that your colleague can use. An Excel data file will help your colleague a lot more than printouts you could send instead because the data is directly accessible.

Plain data — text and numbers — is one thing, but importing and exporting images is quite another. Images are complex because they present graphics — a visual medium — as a series of 0s and 1s (raster graphics) or in terms of points on a Cartesian plane (vector graphics). In addition, some image formats have quirks, such as data compression, that make them hard to work with. This chapter provides a deeper look into working with image files of various sorts.

Tip Data import and export are among the few activities for which many people find using the GUI easier than typing commands. (The choice you make depends on the complexity of the data and just what you want to achieve by importing or exporting it.) Yes, you can type commands to perform the tasks, and you can add import and export commands to your applications, but importing or exporting complex data manually is often easier using the GUI. This chapter focuses on working with commands. However, you can see how to use the GUI in the “Importing” and “Exporting” sections of Chapter 4. These sections also discuss issues such as which file formats MATLAB supports.

Remember You don’t have to type the source code for this chapter manually. In fact, using the downloadable source is a lot easier. You can find the source for this chapter in the \MATLAB2\Chapter16 folder of the downloadable source. When using the downloadable source, you may not be able to work through some of the hands-on examples because the example files will already exist on your system. In this case, you can create an alternative folder, Chapter16a, to hold the results of the hands on exercises. See the Introduction for details on how to obtain the downloadable source.

Importing Data

For most people, importing data from various sources is almost a daily chore because our world is based on interconnectivity. Having as much data as possible to perform a task is critical if you want to obtain good results. That’s why knowing just how to get the data into MATLAB is so important. It’s not just a matter of getting the data, but getting it in such a manner that it can be truly useful. In addition, the import process can’t damage the data in any way; otherwise it could become useless to you in the long run.

Remember A lot of people get the whole business of the importing and exporting of data confused. Importing data always involves taking outside information — something generated externally — and bringing it into a host application, such as MATLAB (as contrasted to exporting, which sends information from MATLAB to an external target). So, when someone sends you a file with Excel data, you must import it into MATLAB in order to use it.

The following sections describe the essentials for importing data into MATLAB from various sources.

Avoiding older import/export function calls

You find code online all the time that talks about using particular functions to perform import and export tasks, but these functions are outdated. The code still might work in your version of MATLAB, but it likely won’t work very long. Consequently, you need to verify functions if you have any doubt about their reliability and longevity (such as code found on older sites). The following list shows common older function calls and their replacements:

Older Function

Replacement

csvread()

readmatrix()

csvwrite()

writematrix()

dlmread()

readmatix()

dlmwrite()

writematrix()

xlsfinfo()

sheetnames()

xlsread()

readtable(), readmatrix(), or readcell()

xlswrite()

writetable(), writematrix(), or writecell()

Performing import basics

A basic import uses all the default settings, which works fine for many kinds of data. MATLAB can determine the correct data format relatively often.

Remember An essential part of importing data is to use the correct import function. Each import function has features that make it more suitable to a particular kind of data. Here are some of the text-specific import functions and how they differ:

· readmatrix(): Can import numbers, strings, and other data formats, unlike csvread() and dlmread(), which MathWorks no longer recommends and which don’t appear in this chapter because they were data type–specific. You may encounter these functions in online examples and need to avoid the examples if you do. This function automatically detects the file import parameters and works with these file types: .txt, .dat, or .csv for delimited text files, and .xls, .xlsb, .xlsm, .xlsx, .xltm, .xltx, or .ods for spreadsheet files.

· textscan(): Can import both numbers and strings. You must provide a format specification to read the data correctly.

· readtable(): Can import both numbers and strings. The output from this function is always a table, even when the source doesn’t contain tabular data. This function supports the same file formats as readmatrix().

The output you receive depends on the function you use. For example, when working with readtable(), you actually get a table as output, not a matrix or a cell array. On the other hand, using readmatrix() results in a matrix as output. There are ways to obtain the kind of output you want, but you need to understand that you start with a specific kind of output data from these functions.

The examples found in the sections that follow each use a different method of reading the data from the disk. However, they all use the same data so that you can compare the results. Here’s the data found in the NumericData.csv file supplied with the downloadable source code:

15,25,30

18,29,33

21,35,41

Using readmatrix()

Using readmatrix() enables you to read a Comma-Separated Value (CSV) or spreadsheet file without a problem. For this example, all you do is type CSVOutput = readmatrix('NumericData.csv') and press Enter. The output is a matrix that contains the following results:

CSVOutput =

15 25 30

18 29 33

21 35 41

Tip Each of the file formats that readmatrix() supports offers options that you can add as a second argument. These options appear as part of the objects listed here for the particular file type:

· Fixed-width text files: FixedWidthImportOptions (see https://www.mathworks.com/help/matlab/ref/matlab.io.text.fixedwidthimportoptions.html for details)

· Spreadsheet files: SpreadsheetImportOptions (see https://www.mathworks.com/help/matlab/ref/matlab.io.spreadsheet.spreadsheetimportoptions.html for details)

· Text files: DelimitedTextImportOptions (see https://www.mathworks.com/help/matlab/ref/matlab.io.text.delimitedtextimportoptions.html for details)

The options are remarkably complete, and if you don’t supply options of your own, MATLAB supplies them for you. To see the default options, simply type the name of the option object, such as delimitedTextImportOptions, and press Enter. Figure 16-1 shows typical output.

Snapshot of the list of options for a readmatrix() call are remarkably complete.

FIGURE 16-1: The list of options for a readmatrix() call are remarkably complete.

To create your own list of options, type opts = delimitedTextImportOptions; and press Enter; then modify individual property values. For example, if the file has the variable names in the first line, then you type opts.VariableNamesLine = 1 and press Enter.

Using textscan()

The textscan() function can read both strings and numbers in the same data set. In addition, it can read some types of data that readmatrix() might encounter difficulty with, such as binary numbers. However, you must define a format specification to use this function. Also, you can’t simply open the file and work with it without knowing the following:

· Whether the file is encoded in some way (perhaps using UTF-7 bit, see a discussion of UTF-8 versus UTF-7 at https://www.techwalla.com/articles/utf-7-vs-utf-8)

· Whether the file contains special control characters (some delimited files use a vertical tab for columns and form feeds for new lines as described at https://community.denodo.com/answers/question/details?questionId=9060g000000L6vVAAS)

With these requirements in mind, you can use the following steps to help you use the textscan() function.

1. Type FileID = fopen('NumericData.csv') and press Enter.

The textscan() function can’t open the file for you. However, it does accept the identifier that is returned by the fopen() function. The variable, FileID, contains the identifier used to access the file.

2. Type TSOutput = textscan(FileID, '%d,%d,%d/n') and press Enter.

You get a single row of the data as output — not all three rows. So, this is a time when you’d normally use a loop to read the data. However, there is more to see, so the example doesn’t use a loop. In this case, the data is read into a cell array, not a matrix. Note that you can find a list of the format specifiers at https://www.mathworks.com/help/matlab/ref/textscan.html#btghhyz-1-formatSpec.

3. Type feof(FileID) and press Enter.

The function outputs a 0, which means that you aren’t at the end of the file yet. You might have wondered how you were going to tell the loop to stop reading the file. A simple test using the feof() function takes care of that problem.

4. Type TSOutput = [TSOutput; textscan(FileID, '%f,%f,%f/n')] and press Enter.

You now see the second row of data read in. However, look at the format specification. These numbers are read as floating-point values rather than integers. Using textscan() gives you nearly absolute control over the appearance of the data in your application.

5. Type isinteger(TSOutput{1,1}) and press Enter.

The output value of 1 tells you that the element at row 1, column 1 is indeed an integer.

6. Type isinteger(TSOutput{2,1}) and press Enter.

This step verifies that the element at row 2, column 1 isn’t an integer because the output value is 0. It pays to ensure that the data you have in MATLAB is the type you actually expected.

7. Type TSOutput = [TSOutput; textscan(FileID, '%2s,%2s,%2s/n')] and press Enter.

Remember This time, the data is read in as individual strings. However, notice that the format specification includes a field width value. If you had simply told textscan() to read strings, it would have read the entire row as a single string into one cell.

8. Type textscan(FileID, '%d,%d,%d/n') and press Enter.

This read should take you past the end of the file. The output is going to contain blank cells because nothing is left to read.

9. Type feof(FileID) and press Enter.

This time, the output value is 1, which means that you are indeed at the end of the file.

10. Type fclose(FileID) and press Enter.

MATLAB closes the file.

Warning Failure to close a file can cause memory leaks and all sorts of other problems. Not closing the file could quite possibly cause data loss, access problems, or a system crash. The point is that you really don’t want to leave a file open after you’re done using it.

Now that you have a better idea of how a textscan() should work, it’s time to see an application that uses it. Listing 16-1 shows how you might implement the preceding procedure as a function. You can also find this function in the UseTextscan.m file supplied with the downloadable source code.

LISTING 16-1 Using textscan() in an Application

function [ ] = UseTextscan( )

%UseTextscan: A demonstration of the textscan() function

% This example shows how to use textscan() to scan

% the NumericData.csv file.



FileID = fopen('NumericData.csv');

TSOutput = textscan(FileID, '%d,%d,%d/n');

while not(feof(FileID))

TempData = textscan(FileID, '%d,%d,%d/n');

if feof(FileID)

break;

end

TSOutput = [TSOutput; TempData];

end

disp(TSOutput);

fclose(FileID);

end

You have already used most of this code as you worked through the exercise, but now you see it all put together. Notice that you must verify that you haven’t actually reached the end of the file before adding the data in TempData to TSOutput. Otherwise, you end up with the blank row that textscan() obtains during the last read of the file.

Using readtable()

The readtable() function is a lot easier to use than textscan(), but it also has a few quirks, such as its assumption that the first row of data is actually column names. To use readtable() with the NumericData.csv file, type RTOutput = readtable('NumericData.csv', 'ReadVariableNames', false) and press Enter. You see the following output:

RTOutput =

3×3 table

Var1 Var2 Var3

____ ____ ____

15 25 30

18 29 33

21 35 41

The output actually is a table rather than a matrix or cell array. The columns have names attached to them, as shown in Figure 16-2. As a consequence, you can access individual members using the variable name, such as RTOutput{1, 'Var1'}, which outputs a value of 15 in this case.

Notice that readtable() accepts property name and value pairs as input. In this case, 'ReadVariableNames' is a property. Setting this property to false means that readtable() won’t read the first row as a heading of variable names. You use readtable() where the output file does contain variable names, because having them makes accessing the data easier in many situations.

Snapshot of tables provide names for each of the columns.

FIGURE 16-2: Tables provide names for each of the columns.

Importing mixed strings and numbers

Life isn’t all about numbers. In some situations, you need to work with a mix of strings and numbers. Each function has its own particular capability. For example, readmatrix() makes it easy to specify the output type of the data with some independence over the data file (you can read an integer as a float or a string, as an example; see the earlier “Using readmatrix()” section for details). Likewise, textscan() provides absolute control over how the data is converted (as described in the “Using textscan()” section, earlier in this chapter).

The readtable() function is designed more for work with database output, for which the output file likely has header names. The database could reside in a Database Management System (DBMS) or as part of a spreadsheet. The source of the data doesn’t matter — only the format does. For this example, you have an output file that contains both row and column headings, as shown here (you can also find this data in the MixedData.csv file supplied with the downloadable source code):

ID,Name,Age,Married

1234,Sam,42,TRUE

2345,Sally,35,TRUE

3456,Angie,22,FALSE

4567,Dan,55,FALSE

The first row isn’t part of the data used for analysis because it contains the row headers. The readtable() function has features to handle extras like row headers. You can see these features described at https://www.mathworks.com/help/matlab/ref/readtable.html, which also demonstrates a few in the example.

To see readtable() in action with the MixedData.csv file, type MixedData = readtable('MixedData.csv') and press Enter. You see the following output:

MixedData =

4×4 table

ID Name Age Married

____ _________ ___ _________

1234 {'Sam' } 42 {'TRUE' }

2345 {'Sally'} 35 {'TRUE' }

3456 {'Angie'} 22 {'FALSE'}

4567 {'Dan' } 55 {'FALSE'}

Notice that the columns have the appropriate names and that each row has the expected identifier (as the ID column). However, the Married column is of the wrong type (it’s currently a string). Follow these steps to fix this problem:

1. Type opts = detectImportOptions('MixedData.csv') and press Enter.

You see the default options that MATLAB will use to read the data from the file. More important, opts now contains those options.

2. Type getvaropts(opts, 'Married') and press Enter.

This function outputs the specific options for the Married column, which includes a Type field value of 'char'. By default, readtable() converts logical values to 'char' equivalents.

3. Type opts = setvartype(opts, 'Married', 'logical') and press Enter.

The Married column will now appear as a logical value when you use opts with readtable().

Now when you type MixedData = readtable('MixedData.csv', opts, 'ReadRowNames', true) and press Enter, MixedData contains Married as a logical value. In addition, by adding the 'ReadRowNames' argument, the table in memory contains an index value as shown here:

ID Name Age Married

________ _________ ___ _______

1234 {'1234'} {'Sam' } 42 true

2345 {'2345'} {'Sally'} 35 true

3456 {'3456'} {'Angie'} 22 false

4567 {'4567'} {'Dan' } 55 false

You can modify the formats of any other import columns using the same technique. For example, notice that ID is now a string column, but you could change it back to a numeric column should you wish to do so. The index column, which contains the row names, always appears in the leftmost output column. The table has a few interesting features. For example, type MixedData('1234', 'Age') and press Enter. You see the following output:

ans =

table

Age

___

1234 42

The output is actually a table that contains just the value you want. Notice the use of parentheses for the index. Using identifiable names rather than numeric indexes is also quite nice.

However, you can access the information as actual data rather than as a table. Type MixedData{'1234', 'Age'} and press Enter. In this case, you obtain a simple output of 42. The use of curly braces means that you get a data value rather than a table as output. It is still possible to use numeric indexes if you want. Type MixedData{1, 2} and press Enter. You obtain the same output value of 42 as you did before.

Technical Stuff If you use versions of MATLAB before R2020a, you might encounter issues when the delimiters or other formatting used in a file was other than expected. For example, the use of semicolons, rather than commas, between fields could cause problems. Newer versions of MATLAB, such as the one used for this book, automatically work well with all sorts of file formatting, so you may need to remove some of the old properties, such as 'Delimiter', from your code to keep it up to date.

Importing selected rows or columns

Sometimes you don’t need an entire file, only certain rows and columns of it. All the functions described earlier in the chapter provide some means of selecting specific information, but the readmatrix() function supplies a straightforward example of how to perform this task. Use these steps to see just a range of data:

1. Type opts = detectImportOptions('NumericData.csv'); and press Enter.

The opts variable now contains the options used to import data, which includes importing the entire file.

2. Type preview('NumericData.csv', opts) and press Enter.

Tip The preview() function lets you obtain a quick view (up to eight rows) of what the various options will do for you. It isn’t meant to give you a full view of the import, and using it can save you time as you experiment. In this case, you see the following output:

ans =

3×3 table

Var1 Var2 Var3

____ ____ ____

15 25 30

18 29 33

21 35 41

3. Type opts.SelectedVariableNames = [1:2]; and press Enter.

This command selects Var1 and Var2 for the output, but excludes Var3.

4. Type opts.DataLines = [1:2]; and press Enter.

This command selects the first two rows of data (1:2 means rows 1 through 2).

5. Type CSVOutput = readmatrix('NumericData.csv', opts) and press Enter.

You see the following output:

CSVOutput =

15 25

18 29

Tip If you want to keep the variable names, you use readtable() instead. Oddly enough, you can use the same opts variable, so you can play around with the data with greater ease than ever before.

Exporting Data

After you perform the calculations that you want to perform, you often need to put them in a form that others can use. However, not everyone has a copy of MATLAB on his or her computer, so you need to export the MATLAB data in some other form. Fortunately, getting the data out in a usable form is actually easier than importing it. The following sections describe how to export data, scripts, and functions.

Performing export basics

Importing data often focuses on getting the right results. For example, you might use textscan() or readtable() on a comma-separated value file, even though a perfectly usable readmatrix() function exists to perform the task. The goal is to get the data from the .csv file into MATLAB and preserve both the content and layout of the original information. However, now that you have data inside MATLAB and want to export it, the goal is to ensure that the resulting file is standardized so that the recipient has minimal problems using it. Therefore, you’d use writetable() only if the recipient really did require a custom format rather than a standard .csv file, or if the MATLAB data was such that you had to use something other than writematrix(). Because of the difference in emphasis, the following sections of the chapter focus on standardized export techniques.

Working with matrices and numeric data

Before you can do anything with exporting, you need data to export. Type ExportMe = [1, 2, 3; 4, 5, 6; 7. 8, 9] and press Enter. You see the following result:

ExportMe =

1 2 3

4 5 6

7 8 9

The result is a matrix of three rows and three columns. Exporting matrices is simple because the majority of the functions accept a matrix as a default. To see how exporting matrices works, type writematrix(ExportMe, 'ExportedData1.csv') and press Enter. MATLAB creates the new file, and you see it appear in the Current Folder window. When you open the file, you see something like the output shown in Figure 16-3. (What you see precisely will vary, depending on the application you use to view .csv files.)

Snapshot of matrices provide the easiest source for export.

FIGURE 16-3: Matrices provide the easiest source for export.

Tip Not all MATLAB data comes in a convenient matrix. When you use writematrix(), you must supply a matrix. To get a matrix, you may have to convert the data from the existing format to a matrix using a conversion function. For example, when the data appears as a cell array, you can use the cell2mat() function to convert it. However, some conversions aren’t so straightforward. For example, when you have a table as input, you need to perform a two-step process:

1. Use the table2cell() function to turn the table into a cell array.

2. Use the cell2mat() function to turn the cell array into a matrix.

Fortunately, you can skip some conversions if you want. For example, instead of converting your cell array into a matrix, you can output it using writecell().

Working with mixed data

Exporting simple numeric data is straightforward because you have a number of functions to choose from that create the correct formats directly. The problem comes when you have a cell array or other data form that doesn’t precisely match the expected input for one of the output functions. To see how mixed data works, start by typing MyCellArray = {'Andria', 42, true; 'Michael', 23, false; 'Zarah', 61, false} and pressing Enter. You see the following result:

MyCellArray =

3×3 cell array

{'Andria' } {[42]} {[1]}

{'Michael'} {[23]} {[0]}

{'Zarah' } {[61]} {[0]}

The easiest way to export this data to a CSV file is to type writecell(MyCellArray, 'ExportedData2.csv') and press Enter. Note that writecell() converts the third column from logical to text in the process.

Remember If you want to preserve the data format, you must use some other export format, such as Excel. In this case, you type writecell(MyCellArray, 'ExportedData2.xls') and press Enter. Figure 16-4 shows that the exported data now appears in the correct types. The point is that MATLAB preserves the data format only if you use the correct output file format.

Snapshot of using the correct export format makes it possible to preserve the data format.

FIGURE 16-4: Using the correct export format makes it possible to preserve the data format.

Using a nontext file format can have other advantages as well. For example, when working with the Excel format, you gain access to the ability to store different data on different sheets. You can also specify a range in which to store the data. The documentation at https://www.mathworks.com/help/matlab/ref/writecell.html provides additional insights into the properties you can use to modify how MATLAB exports your data.

Exporting scripts and functions

To export scripts and functions, you must actually publish them using the publish() function. MATLAB supports a number of output formats for this purpose. For example, if you want to publish the UseTextscan() function, which appears earlier in the chapter in HTML format, you type publish('UseTextscan.m', 'html') and press Enter. MATLAB provides the following output:

ans =

'C:\MATLAB2\Chapter16\html\UseTextscan.html'

The actual location varies by system, but you also obtain the location of the published file. Notice that MATLAB places the published file in an html subdirectory. Figure 16-5 shows typical output. (What you see may differ based on your platform and the browser that you use.)

Publishing is a much larger topic than can fit in a single section of a chapter. Chapter 17 discusses publishing in considerably greater detail.

Snapshot of publishing the scripts and functions to export them.

FIGURE 16-5: To export scripts and functions, you must publish them.

Working with Images

Images are more complex than text files because they use binary data that isn’t easy for humans to understand, and the format of that data is intricate. Small, hard-to-diagnose errors can cause the entire image to fail. However, the process of exporting and importing images is relatively straightforward, as described in the following sections.

Exporting images

Before you can export an image, you need an image to export. The “Using the bar( ) function to obtain a flat 3D plot” section of Chapter 7 describes how to create the 3D bar graph shown in Figure 16-6. (You can also create the bar chart using the CreateBarChart.m script found in the downloadable source code.) This is the image used for the remainder of this chapter.

Snapshot of creating an image to export from MATLAB.

FIGURE 16-6: Create an image to export from MATLAB.

Before you export the image, you must decide on the parameters for the output. The most important parameter is the output type. Because Joint Photographic Experts Group (.jpeg) files are common on most platforms, the example uses a .jpeg. However, you can use any of the file formats listed in the Image section of the chart at http://www.mathworks.com/help/matlab/import_export/supported-file-formats.html.

After you decide on an export format, you can use the saveas() function to perform the task. In this case, you type saveas(gcf(), 'Bar1.jpeg', 'jpg') and press Enter. MATLAB exports the figure using whatever resolution is currently set for the figure. Remember that the gcf() function obtains the handle for the current figure. Figure 16-7 shows the plot in Windows Photo Viewer as Bar1.jpeg.

Snapshot of the output image showing the plot as Windows Photo Viewer sees it.

FIGURE 16-7: The output image shows the plot as Windows Photo Viewer sees it.

Tip Use the saveas() function to save MATLAB objects, such as plots. However, when working with actual images, use the imwrite() function instead. The imwrite() function works essentially the same way that saveas() does, but it works directly with image files.

Importing images

MATLAB can also work with images that you import from other sources. The basic method of importing an image is to use imread(). For example, to import Bar1.jpeg, you type ImportedImage = imread('Bar1.jpeg') and press Enter. What you see as output is a matrix that has the same dimensions as the image. If the image has a resolution of 900 x 1200, the matrix will also be 900 x 1200. However, a third dimension is involved — the color depth. It takes red, green, and blue values to create a color image. So the resulting matrix is actually 900 x 1200 x 3.

Remember This is one of those situations in which the semicolon is absolutely essential at the end of the command. Otherwise, you may as well go get a cup of coffee as you wait for the numbers to scroll by. If you accidentally issue the command without the semicolon, you can always stop it by pressing Ctrl+C.

To display your image, you use the image() function. For example, to display the image you just imported, you type image(ImportedImage) and press Enter. Figure 16-8 shows the result of importing the image. You see the original plot, but in image form.

Snapshot of seeing the plot in image form.

FIGURE 16-8: Seeing the plot in image form.

If you find an error or have any questions, please email us at admin@erenow.org. Thank you!