1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
|
#!/usr/bin/awk -f
#
# Performs interpolation for columns in a CSV and outputs the result
#
# Copyright (C) 2016 LoVullo Associates, Inc.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# Configurable values (use -vname=value from command line):
# step - use predeterminated step instead of calculating from first two rows
##
function storeline()
{
for ( i = 1; i <= hlen; i++ ) {
prev[i] = $i
}
}
function clearline()
{
for ( i = 1; i <= hlen; i++ ) {
prev[i] = 0
}
}
function getprev()
{
for ( i = 1; i <= hlen; i++ ) {
$i = prev[i]
}
}
function interpolate()
{
lastval = prev[1]
curval = $1
diff = curval - lastval
# does this value fall in line with the requested step?
if ( diff == step )
{
storeline()
# we're good; continue
print
next
}
# if we do not yet have a value large enough to reach our step, then continue
# until we do (do not store this line)
n = int( diff / step )
if ( n <= 0 ) {
next
}
# determine interpolation values
for ( i = 2; i <= hlen; i++ ) {
ival[i] = ( ( $i - prev[i] ) / n )
}
getprev()
# let us interpolate values that are divisible by the step
do
{
# increase the last value by our step
$1 += step
# interpolate each column value (notice that we skip the first column, which
# was handled directly above)
for ( i = 2; i <= hlen; i++ ) {
$i += ival[i]
}
# print the new line
print
} while ( ( diff -= step ) > 0 )
# anything remaining does not fit into our step and will be ignored; we'll
# continue with our next step at the next line
# consider this to be our last line
storeline()
}
BEGIN {
# the first row of the CSV is the header representing the column identifiers
getline
hlen = split( $0, header, /,/ )
# output the header
print $0
# delimit fields by commas (the field separator for CSVs); note that this
# won't work properly if strings contain commas
FS = OFS = ","
clearline()
getline
# if no step was provided, then calculate one based on the first two rows
if ( step == 0 ) {
# output the first row, which does not need to be interpolated
print
# compute the step
vala = $1
getline
valb = $1
step = valb - vala
# since the second line is used to determine the step, then it must match the
# step and therefore is good to output
print
# begin.
storeline()
}
}
# for each row
{ interpolate() }
|