2
$\begingroup$

I have a modest number of .csv files that I want to import into mathematica. I would like to save their contents as their filebasename for use throughout my notebook, but I am running into errors as shown below. The .csv files have dimensions of 64x3 and have filenames:

{"G1BCM.csv", "G1EXP.csv", "G1FIM.csv", "G1IAM.csv"}

Here is my attempt:

files = FileNames["*.csv", NotebookDirectory[]];
data = Import[#] & /@ files;

filenames = {};
Do[AppendTo[filenames, FileBaseName[files[[i]]]], {i, Length[files]}];

MapThread[Set, {filenames, data}]

I have seen MapThread used in this way before, but here it yields a string of errors:

Set::setraw: Cannot assign to raw object G1BCM. >>
Set::setraw: Cannot assign to raw object G1EXP. >>
Set::setraw: Cannot assign to raw object G1FIM. >>
General::stop: Further output of Set::setraw will be suppressed during this calculation. >>

{data} (*which I am not going to bother copying*)

This code successfully pulls the data from each of the .csv files and successfully pulls the filebasenames, such that:

In[158]:= filenames

Out[158]= {"G1BCM", "G1EXP", "G1FIM", "G1IAM"}

This seems like it should set up the MapThread function appropriately. What have I done wrong?

At the end of the day, I want to automate G1BCM=data[[1]], G1EXP=data[[2]], etc. With G1BCM automatically pulled from G1BCM.csv and data[[1]]=the contents of G1BCM.csv.

I have also tried things like:

Do[filenames[[i]] := data[[i, All, All]], {i, Length[files]}]

But, of course, this just rewrites the elements of the filenames list, and I do not know how to treat elements of a list as variables other than through the MapThread function.

$\endgroup$
  • 1
    $\begingroup$ Your MapThread command is trying to assign a value to a string. Try changing it to MapThread[Set, {ToExpression /@ filenames, data}] $\endgroup$ – mfvonh Oct 1 '15 at 22:04
  • $\begingroup$ Symbol/@ may work as well. $\endgroup$ – george2079 Oct 2 '15 at 0:13
  • $\begingroup$ @mfvonh That worked! Thank you very much! $\endgroup$ – Snipatomic Oct 2 '15 at 18:07
  • 1
    $\begingroup$ note Set threads on its own so you don't need MapThread : Set @@ {Symbol /@ filenames, data} $\endgroup$ – george2079 Oct 2 '15 at 18:29
  • $\begingroup$ could you please update the title of your question to something which makes sense? $\endgroup$ – chris Oct 2 '15 at 18:38
4
$\begingroup$

Here is a different approach (for the solution of your problem see @mfvonh solution). What I would probably do in your case would be to create one "database" containing all your data.

Let's say you have your file names:

files = {"G1BCM.csv", "G1EXP.csv", "G1FIM.csv", "G1IAM.csv"};

then you can create a database as simply as:
(In your case, just replace here below foo with Import)

db = Association[Map[Rule[FileBaseName[#], foo[#]] &, files]]

<|G1BCM->foo[G1BCM.csv],G1EXP->foo[G1EXP.csv],G1FIM->foo[G1FIM.csv],G1IAM->foo[G1IAM.csv]|>

Then, for example to get the "data" (values) corresponding to "G1BCM" (key) just type:

db["G1BCM"]

foo["G1BCM.csv"]

(in your case, foo[...] will be replaced with real data)

$\endgroup$
  • $\begingroup$ Thank you very much for your answer. So, this worked, but with the structure of the rest of my code, it is a bit more convenient to have each saved as a separate variable. I will keep this structure in mind in the future though. I have not yet worked with associations much as I just recently upgraded to V10.2. $\endgroup$ – Snipatomic Oct 2 '15 at 18:10
  • $\begingroup$ @Snipatomic You're welcome ! $\endgroup$ – SquareOne Oct 2 '15 at 18:44
2
$\begingroup$

Many thanks to @mfvonh for this answer (posted as a comment below my question).

The issue was that I was trying to assign values to strings. using ToExpression to convert the strings to expressions worked beautifully. My final code is as follows:

files = FileNames["*.csv", NotebookDirectory[]];
data = Import[#] & /@ files;

filenames = {};
Do[AppendTo[filenames, FileBaseName[files[[i]]]], {i, Length[files]}];

MapThread[Set, {ToExpression /@ filenames, data}]

This does exactly what I wanted. Thank you all for your help!


EDIT:

As @george2079 mentioned, Set threads on its own so MapThread is unneeded. A more elegant line would then be the following (replacing MapThread):

Set @@ {Symbol /@ filenames, data}
$\endgroup$
1
$\begingroup$

If you don't have V.10 Associations are out otherwise @SquareOne's solution is the better choice. Anyway quick and dirty solution I've used in the past is:

filenames = {"a", "b", "c", "d"};
data = {12, 20, 40, 60};
d = MapThread[Rule, {filenames, data}];

Then accessing data for a particular name is done with

  "a"/.d

Obviously, replace filenames and data. But it looks like you have that part covered.

$\endgroup$
  • $\begingroup$ This is exactly what I was trying to do, but as @mfvonh mentioned, I was mistakenly trying to assign values to strings. $\endgroup$ – Snipatomic Oct 2 '15 at 18:13

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.