2

I'm using my Airport utility to get all available WiFi networks around me and I want to display them as a clustered bar chart using gnuplot. I can't figure out, how to transform the data into a form that gnuplot can work with.

My neighbours.dat looks like this:

CHANNEL RSSI SSID
1  -54  DESIGN-DEV
1  -54  DESIGN-EMPLOYEE-DA
1  -54  DESIGN-GUEST
1  -56  DESIGN-DEV
1  -56  DESIGN-EMPLOYEE-DA
1  -56  DESIGN-GUEST
1  -56  cwlanoffice
1  -56  llc-net
1  -66  DESIGN-DEV
1  -66  DESIGN-EMPLOYEE-DA
1  -66  DESIGN-GUEST
6  -56  WLAN-A23120
6  -60  WLAN-73CF94
6  -71  DESIGN-EMPLOYEE-DA
6  -71  DESIGN-GUEST
6  -72  DESIGN-DEV
6  -74  ecp-eco2016
6  -75  cwlanoffice
6  -75  llc-net
6  -76  CWLANGuest
6  -84  CWLANGuest
6  -84  TIMTIM
6  -85  llc-net
11  -39  WLAN-BKH64S
11  -67  cwlanoffice
11  -67  llc-net
11  -69  CWLANGuest
36  -57  WLAN-73CF94
36  -89  CWLANGuest
36  -89  cwlanoffice
36  -90  llc-net
44  -65  CWLANGuest
44  -66  cwlanoffice
44  -66  llc-net
44  -80  ecp-eco2016
52  -40  WLAN-BKH64S
52  -56  DESIGN-DEV
52  -56  DESIGN-GUEST
52  -57  DESIGN-EMPLOYEE-DA
100  -73  DESIGN-DEV
100  -73  DESIGN-GUEST
100  -74  DESIGN-EMPLOYEE-DA
108  -47  DESIGN-DEV
108  -47  DESIGN-EMPLOYEE-DA
108  -47  DESIGN-GUEST
108  -61  DESIGN-DEV
108  -61  DESIGN-EMPLOYEE-DA
108  -62  DESIGN-GUEST
132  -66  CWLANGuest
132  -66  cwlanoffice
132  -66  llc-net

For the bar chart, I need to put it into this format—with the SSIDs as my columns and the CHANNELs as my rows:

         SSID1   SSID2   SSID3   SSID4   SSID5
Channel1 -56     -20     -19             -47
Channel2         -38     -21             -28

Can you help me achieve this? My latest attempt is using the unique SSIDs and try to create a table with with them.

sort -k3 -u neighbours.dat | awk '{print $3}' > neighbours-ssids.dat

c=$(wc -l < neighbours-ssids.dat)

echo $c

for (( i = 0; i < $c; i++ )); do
  awk 'NR=='$i neighbours-ssids.dat
done
Mike
  • 21
  • 3
  • I do not understand the table format you would like to achieve. For example, what do you do when a SSID has multiple entries for the same channel (for example, DESIGN-DEV has three entries for channel 1)? – user8153 Jun 04 '18 at 23:31
  • @user8153 Exactly. That is something I just now understood. For my purpose, I'm using `tail -n 1` to only work with the highest value. The format of the table is supposed to look something like in [this example](https://stackoverflow.com/questions/5130517/clustered-bar-plot-in-gnuplot?answertab=votes#tab-top). – Mike Jun 05 '18 at 13:53

1 Answers1

0

A gawk solution could be as follows:

BEGIN {
  num_of_ssids = 0
  num_of_channels = 0
}
{
  ssid = $3
  if (!(ssid in data_ssid)) {
    data_ssid[ssid] = num_of_ssids;
    idx_to_ssid[num_of_ssids] = ssid;
    num_of_ssids++;
  }

  channel = $1
  if (!(channel in data_chanel)) {
    data_chanel[channel] = num_of_channels;
    idx_to_channel[num_of_channels] = channel;
    num_of_channels++;
  }

  data[channel][ssid] = $2
}

END{
  for(j=0;j<num_of_ssids;j++) {
    ssid = idx_to_ssid[j];
    printf "\t%s", ssid;
  }
  printf "\n";

  for(i=0;i<num_of_channels;i++) {
    channel = idx_to_channel[i];
    printf "%s", channel;

    for(j=0;j<num_of_ssids;j++) {
      ssid = idx_to_ssid[j];
      printf "\t%s", data[channel][ssid]; 
    }
    printf "\n";
  }
}

The idea is to go over the file and for each line:

  1. check if the ssid has been already seen or not (similarly for the channel) and if not then assign to it an incremental index (in order to associate this index with row/column index of the resulting table)
  2. save the corresponding data value into a two-dimensional array indexed by channel and ssid name

At the end of the script, one can iterate over all unique channel/ssid names and print the corresponding value in a form of a table.

ewcz
  • 12,819
  • 1
  • 25
  • 47
  • Thanks for the fast answer. I'm trying it like this—the double `for loop` seemed like a rather unelegant solution to me, but it is slowly moving in the right direction. – Mike Jun 05 '18 at 13:50