MATLAB Answers

Elements of table equal to elements of another table

37 views (last 30 days)
Daphne PARLIARI on 24 Jan 2020
Commented: Guillaume on 27 Jan 2020
Hi all!
I have a list of stations (see .txt) and a .csv (see attached) with several data. What I need to do is scan the entire .txt and for every station, eg. Airport, to go and scan column 14 of the .csv. If the station is the same, I want to do several things, eg. extract the date (column 2) and Temperature (column 15) every time Airport appears.
I tried with eq but it doesn't work.
list1 = rdir ('C:\Projects\LIFE ASTI\C.3\C.3\Weather station data\from desktop\Obs. data 4 Keppas\');
wrfdir = 'C:\Projects\LIFE ASTI\C.3\C.3\Weather station data\from desktop\2019 run\Thess\*.csv';
stations = readtable('C:\Projects\LIFE ASTI\C.3\C.3\Weather station data\from desktop\Stations coordinates.txt');
output_path='C:\Projects\LIFE ASTI\C.3\C.3\Weather station data\from desktop\OutputSimulations';
WRF_Data = readtable('C:\Projects\LIFE ASTI\C.3\C.3\Weather station data\from desktop\2019 run\Thess\THESS_Temp.csv');
% Variables
vars={'Temperature'; 'Relative humidity'};
years = {'2015'; '2019'};
varunits={'Celsius'; '%' };
%Starting loop for all files
for i=1:size(stations,1)
for k = 1:size(WRF_Data.Station,1)
if eq(stations(i,1) , WRF_Data.Station(k,1))


Sign in to comment.

Accepted Answer

Guillaume on 24 Jan 2020
I'm not entirely clear what the ultimate goal is but one thing for sure, you don't need a loop at all.
To keep only the rows of WRF_Data that have a station in stations AND append the rest of the station variables to these rows, it's simply:
merged = innerjoin(WRF_Data, stations, 'Keys', 'Station'); %And you don't even need the 'Keys', 'stations' although it makes the code clearer.
If you don't want all the variables in the output, you can tell innerjoin which one you want:
merged = innerjoin(WRF_Data, stations, 'LeftVariables', {'Station', 'Var1', 'Temp'}, 'RightVariables', {'Lat', 'Lon'}) %for example


Show 5 older comments
Guillaume on 27 Jan 2020
I recommend you use the import code I wrote.
You can modify the anonymous function in the splitapply code to do whatever you want, eg. to save into individual directories named after the station:
rootpath = 'C:\somewhere\somefolder';
[group, stations] = findgroups(merged.Station);
splitapply(@(rows, statidx) writetable(merged(rows, :), fullfile(rootpath, stations{statidx(1)}, 'station.csv')), (1:height(merged))', group, group);
Or if it's too complex, use a loop:
rootpath = 'C:\somewhere\somefolder';
[group, stations] = findgroups(merged.Station);
for gidx = 1:numel(stations) %iterate over each unique station group
writetable(merged(group = gidx, :), fullfile(rootpath, stations{gidx}, 'station.csv'));
Daphne PARLIARI on 27 Jan 2020
Great, thank you!
If you have time, could you please explain to me what each of line
splitapply(@(rows, statidx) writetable(merged(rows, :), sprintf('%s.csv', stations{statidx(1)})), (1:height(merged))', group, group);
Guillaume on 27 Jan 2020
splitapply split the input arrays into groups and apply the same function to each group, that is it takes the rows of each input array corresponding to a group and pass that to the function, then it passes the rows corresponding to the next group, etc.
The groups are defined by the last input to splitapply, in this case group. The two arrays that I've decided would be split are (1:height(merged))' which is basically the row indices of the table and group as I actually need the group index to be passed to the processing function. The processing function is the anonymous function: @(rows, statidx) writetable(merged(rows, :), sprintf('%s.csv', stations{statidx(1)})). This is a function with two inputs rows and statidx. rows receives in turn the elements of the first input of splitapply: (1:height(merged))', that is it receives the row indices of the table corresponding to a group (a station), statidx receives in turn the elements of the 2nd input, group corresponding to a group, so it's a vector of identical numbers, hence why I use statidx(1) in the function body.
The function body writes the sekect rows of the table to a file whose name is the station. If we were to rewrite the anonymous function, it would be more or less
function anonfun(rows, statidx)
%rows: row indices of the table corresponding to a single station. Column vector
%statidx: column vector of identical values containing the station/group number
%Unlike normal function, anonymous functions can capture variable from the enclosing workspace
%Here, it also captures
%merged: the table
%stations: list of unique station names, ordered by group number
subtable = merged(rows, :); %extract portion of the table corresponding to station
currentstation = stations{statidx(1)};
filename = sprintf('%s.csv', currentstation);
writetable(subtable, filename);
And if you were to write what splitapply does as a loop, it would be (in this case):
input1 = (1:height(merged))'; %row indices of the table
input2 = group;
for g = 1:max(group)
thisgroup_input1 = input1(group == g);
thisgroup_input2 = input2(group == g);
anonfun(thisgroup_input1, thisgroup_input2); %anonfun also captures merged and stations without needing to pass them as arguments

Sign in to comment.

More Answers (1)

Philippe Lebel
Philippe Lebel on 24 Jan 2020
Edited: Philippe Lebel on 24 Jan 2020
Here you go:
I loop over all station names and check where in the data table i find these names. I generate a boolean index in order to fetch data from the table and store them in a structure.
stations = readtable('\Stations coordinates.txt');
WRF_Data = readtable('\THESS_Temp.csv');
%Starting loop for all files
for i=1:size(stations,1)
WRF_Data_station_mask = ismember(WRF_Data(:,14),stations(i,1));
sorted_values(i).name = char(stations{i,1});
sorted_values(i).temps = WRF_Data(WRF_Data_station_mask,15);


Sign in to comment.

Community Treasure Hunt

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

Start Hunting!