Understanding the structfun() or cellfun() commands (2024)

65 views (last 30 days)

Show older comments

Jackson Kock on 23 Apr 2021

  • Link

    Direct link to this question

    https://www.mathworks.com/matlabcentral/answers/811680-understanding-the-structfun-or-cellfun-commands

  • Link

    Direct link to this question

    https://www.mathworks.com/matlabcentral/answers/811680-understanding-the-structfun-or-cellfun-commands

Answered: Stephen23 on 24 Apr 2021

Accepted Answer: dpb

Open in MATLAB Online

Dear All,

I want to avoid the use of for loops by using the structfun() and cellfun() commands.

I have a folder with a bunch of "nnn_M.csv" files, where the "nnn" prefix corresponds to numbering of the files, and the "_M" suffix being constant for all files. My goal is to create a double array of the "nnn" values.

The code I currently use with a for loop: (Works)

Files = dir('*.csv'); % Create the structure of file descriptions (name,datenum,...)

N = length(Files); % Determind # of files for the for loop

for ii = 1:N

FileNames{ii} = Files(ii).name; % Create cell array of the file names

nnn(ii) = sscanf(FileNames{ii},'%d_M'); % Create double array of file prefixes

end

This is the code without a for loop: (Does not work)

Files = dir('*.csv'); % Create the structure of file descriptions (name,datenum,...)

FileNames = structfun(@(x) Files(x).name, Files); % Create cell array of the file names

nnn = cellfun(@(x) sscanf(FileNames{x},'%d_M'),FileNames); % Create double array of file prefixes

The 2nd and 3rd lines give me errors, repectively:

Error using structfun

Inputs to STRUCTFUN must be scalar structures.

% and

Index exceeds the number of array elements (14).

Error in @(x)sscanf(FileNames{x},'%dK')

% When using the correct 'FileNames' the for loop gives

% There are 14 *.csv files in the folder

I welcome all suggestions you may have. Thank you for helping me understand these functions!

Cheers,

-Jackson

0 Comments

Show -2 older commentsHide -2 older comments

Sign in to comment.

Sign in to answer this question.

Accepted Answer

dpb on 24 Apr 2021

  • Link

    Direct link to this answer

    https://www.mathworks.com/matlabcentral/answers/811680-understanding-the-structfun-or-cellfun-commands#answer_683380

  • Link

    Direct link to this answer

    https://www.mathworks.com/matlabcentral/answers/811680-understanding-the-structfun-or-cellfun-commands#answer_683380

Open in MATLAB Online

As the error message and doc says, structfun applies a function to each field in a scalar struct; you have a struct array -- not what you want.

And, for the specific desire you don't need either function nor a loop construct, either -- use MATLAB vectorized notation--

nums=str2double(extractBefore(string({Files.name}),'_'));

2 Comments

Show NoneHide None

Jackson Kock on 24 Apr 2021

Direct link to this comment

https://www.mathworks.com/matlabcentral/answers/811680-understanding-the-structfun-or-cellfun-commands#comment_1479700

  • Link

    Direct link to this comment

    https://www.mathworks.com/matlabcentral/answers/811680-understanding-the-structfun-or-cellfun-commands#comment_1479700

Open in MATLAB Online

Thank you dpb for the answer, which does work as needed.

A couple follow up comments/ questions if I may:

1) I learned that the {} around Files.name creates the cell array of the file names. Such as,

A = {Files.name};

The reason I need to {} is to create the array? Otherwise the command,

A = Files.name;

only knows to grab the first file's name?

2) I do not understand my initial error with the cellfun() command. If you couple please enlighten me on this regard. It seems like the function was doing something but the indexing was incorrect?

3) Could I still use a cellfun() to get the numbers in front of the file name? For example:

A = {Files.name};

B = cellfun(??,A); % I do not know what to put here

I want to understand how to use an arbitrary function inside the cellfun() command to be able to use them in the future. I understand the case of simpler functions, such as:

C = {[1,2],[3,4]};

D = cellfun(@mean,C);

Most appreciated.

dpb on 24 Apr 2021

Direct link to this comment

https://www.mathworks.com/matlabcentral/answers/811680-understanding-the-structfun-or-cellfun-commands#comment_1479950

  • Link

    Direct link to this comment

    https://www.mathworks.com/matlabcentral/answers/811680-understanding-the-structfun-or-cellfun-commands#comment_1479950

Edited: dpb on 24 Apr 2021

Open in MATLAB Online

1) Try at the command line and see what Files.name returns. (Hint: search for "comma-separated list" in doc)

2) Since the first failed, I don't know what the content of the cell array was when you tried it so it's not possible to say just what, but probably you had a smaller array than thought and passed inconsistent ones

3a) Sure, but why? You want to avoid loops; cellfun is a loop in sheep's clothing; underneath it is the loop with more overhead than just the direct for...end construct. It has its place, certainly, but isn't always the better solution. But, for illustration

>> cellfun(@(s)sscanf(s,'%d_M'),{Files.name})

ans =

0 1.00

>>

3b) As the above illustrates, you write an anonymous function in place of the function handle--it can be any one-line expression. Or, if you can't manage it in one line, use a handle to the m-file function you write. NB: one feature of anonymous functions is that the embed any workspace variables not in their argument list in the function body itself -- the same result as above could be obtained by

>> arrayfun(@(i)sscanf(Files(i).name,'%d_M'),1:numel(Files))

ans =

0 1.00

>>

where the Files struct is embedded in the anonymous function. While not optimal here, this can be extremely useful when other parameters are needed to evaluate the function.

Sign in to comment.

More Answers (1)

Stephen23 on 24 Apr 2021

  • Link

    Direct link to this answer

    https://www.mathworks.com/matlabcentral/answers/811680-understanding-the-structfun-or-cellfun-commands#answer_683860

  • Link

    Direct link to this answer

    https://www.mathworks.com/matlabcentral/answers/811680-understanding-the-structfun-or-cellfun-commands#answer_683860

Open in MATLAB Online

  • 1.2_M.csv
  • 3.4_M.csv
  • 5.6_M.csv

Avoiding CELLFUN or STRUCTFUN is simpler and much more efficient:

S = dir('*_M.csv');

V = sscanf([S.name],'%f_M.csv')

V = 3×1

1.2000 3.4000 5.6000

0 Comments

Show -2 older commentsHide -2 older comments

Sign in to comment.

Sign in to answer this question.

See Also

Categories

MATLABLanguage FundamentalsData TypesData Type IdentificationWhos

Find more on Whos in Help Center and File Exchange

Tags

  • structfun()
  • cellfun()

Products

  • MATLAB

Release

R2020a

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

An Error Occurred

Unable to complete the action because of changes made to the page. Reload the page to see its updated state.


Understanding the structfun() or cellfun() commands (6)

Select a Web Site

Choose a web site to get translated content where available and see local events and offers. Based on your location, we recommend that you select: .

You can also select a web site from the following list

Americas

  • América Latina (Español)
  • Canada (English)
  • United States (English)

Europe

  • Belgium (English)
  • Denmark (English)
  • Deutschland (Deutsch)
  • España (Español)
  • Finland (English)
  • France (Français)
  • Ireland (English)
  • Italia (Italiano)
  • Luxembourg (English)
  • Netherlands (English)
  • Norway (English)
  • Österreich (Deutsch)
  • Portugal (English)
  • Sweden (English)
  • Switzerland
    • Deutsch
    • English
    • Français
  • United Kingdom(English)

Asia Pacific

  • Australia (English)
  • India (English)
  • New Zealand (English)
  • 中国
  • 日本Japanese (日本語)
  • 한국Korean (한국어)

Contact your local office

Understanding the structfun() or cellfun() commands (2024)

References

Top Articles
Latest Posts
Article information

Author: Gov. Deandrea McKenzie

Last Updated:

Views: 5767

Rating: 4.6 / 5 (46 voted)

Reviews: 93% of readers found this page helpful

Author information

Name: Gov. Deandrea McKenzie

Birthday: 2001-01-17

Address: Suite 769 2454 Marsha Coves, Debbieton, MS 95002

Phone: +813077629322

Job: Real-Estate Executive

Hobby: Archery, Metal detecting, Kitesurfing, Genealogy, Kitesurfing, Calligraphy, Roller skating

Introduction: My name is Gov. Deandrea McKenzie, I am a spotless, clean, glamorous, sparkling, adventurous, nice, brainy person who loves writing and wants to share my knowledge and understanding with you.