I'm getting a division by 0 error from my awk command. I'm not sure what is causing this as the result should not be 0.
In this case it should be printing 1.11557887 from 1.7229/1.5444.
Could it be a problem with how I assigned the variables?
This is my script:
#!/usr/bin/awk -f
FNR == 22 { measC = $2 }
FNR == 23 { refC = $2 }
factorC = refC / measC
{ print factorC }
It returns:
/usr/bin/awk: division by zero
input record number 1, file 1.txt
source line number 5
This is what my input data looks like:
#!xxx x
# x x x x x x
# x: x x
# x: x x
# x: x x x x x
# (x) x x, x x x, x.
x: x x x x
x: 3.0.0
x: x
x: 0
x: x x
x: 0
x: x x
x: x
x: 0
x: 0
x: 2
x: x x x
x: x
x: 1
x: 4
origmax: 1.5444 1.5188 1.0221 1.4932
currentmax: 1.7229 1.6888 1.1069 1.6238
Because you put factorC = refC / measC outside of a block, awk thinks you want to use that expression as a pattern. So it evaluates that expression for each line of input. On the first line of input, measC hasn't been defined yet, so it defaults to zero.
I think you want this:
#!/usr/bin/awk -f
FNR == 22 { measC = $2 }
FNR == 23 { refC = $2 }
END {
factorC = refC / measC
print factorC
}
or this:
#!/usr/bin/awk -f
FNR == 22 { measC = $2 }
FNR == 23 {
refC = $2
factorC = refC / measC
print factorC
}
Your script says:
FNR == 22 { measC = $2 }
So ... when only, say, five lines of your input file have been read by this awk script, what is the value of measC?
I'll tell you a secret. It will be zero. Because nothing has assigned anything else to measC yet.
Also, your line:
factorC = refC / measC
is outside the block, so it's being used to evaluate whether the { print factorC } should be run. And because it's a condition, it gets run for every line. And wouldn't you know it, before line 22, measC is 0.
I don't understand the data or the output, so I don't know what measC should be, if anything.
What are you trying to achieve with this?
Related
I have a plot whose y min starts well above 0. But I want to include 0 as the min of the y-axis and still have Stata automatically create evenly-spaced y-axis labels.
Here is the baseline:
sysuse auto2, clear
scatter turn displacement
This produces:
This is almost what I want, except that the y range does not start at 0.
Based on this answer by Nick Cox (https://www.statalist.org/forums/forum/general-stata-discussion/general/1598753-force-chart-y-axis-to-start-at-0), I modify the code to be:
scatter turn displacement, yscale(range(0 .)) ylabel(0)
This succeeds in starting the y-axis at 0, but the labeling besides 0 goes away:
I proceed to remove `ylabel(0):
scatter turn displacement, yscale(range(0 .))
This produces the opposite problem - the y-axis labels are the same as in the first plot.
How can I have Stata automatically produce the y-axis labels from 0 to the max? For instance, 0, 10, 20, 30, 40, 50 - importantly, though, I have many plots and need a solution that determines the exact values automatically, without needing me to input the y max, etc. So it would not be me who chooses 10, 20, ..., 50, but Stata.
By coincidence, I have been working on a command in this territory. Here is a reproducible example.
sysuse auto, clear
summarize turn, meanonly
local max = r(max)
nicelabels 0 `max', local(yla)
* shows 0 20 40 60
scatter turn displacement, yla(`yla', ang(h))
nicelabels 0 `max', local(yla) nvals(10)
* shows 0 10 20 30 40 50 60
scatter turn displacement, yla(`yla', ang(h))
where nicelabels is at present this code.
*! 1.0.0 NJC 25 April 2022
program nicelabels
/// fudge() undocumented
version 9
gettoken first 0 : 0, parse(" ,")
capture confirm numeric variable `first'
if _rc == 0 {
// syntax varname(numeric), Local(str) [ nvals(int 5) tight Fudge(real 0) ]
syntax [if] [in] , Local(str) [ nvals(int 5) tight Fudge(real 0) ]
local varlist `first'
marksample touse
quietly count if `touse'
if r(N) == 0 exit 2000
}
else {
// syntax #1 #2 , Local(str) [ nvals(int 5) tight Fudge(real 0) ]
confirm number `first'
gettoken second 0 : 0, parse(" ,")
syntax , Local(str) [ nvals(int 5) tight Fudge(real 0) ]
if _N < 2 {
preserve
quietly set obs 2
}
tempvar varlist touse
gen double `varlist' = cond(_n == 1, `first', `second')
gen byte `touse' = _n <= 2
}
su `varlist' if `touse', meanonly
local min = r(min) - (r(max) - r(min)) * `fudge'/100
local max = r(max) + (r(max) - r(min)) * `fudge'/100
local tight = "`tight'" == "tight"
mata: nicelabels(`min', `max', `nvals', `tight')
di "`results'"
c_local `local' "`results'"
end
mata :
void nicelabels(real min, real max, real nvals, real tight) {
if (min == max) {
st_local("results", min)
exit(0)
}
real range, d, newmin, newmax
colvector nicevals
range = nicenum(max - min, 0)
d = nicenum(range / (nvals - 1), 1)
newmin = tight == 0 ? d * floor(min / d) : d * ceil(min / d)
newmax = tight == 0 ? d * ceil(max / d) : d * floor(max / d)
nvals = 1 + (newmax - newmin) / d
nicevals = newmin :+ (0 :: nvals - 1) :* d
st_local("results", invtokens(strofreal(nicevals')))
}
real nicenum(real x, real round) {
real expt, f, nf
expt = floor(log10(x))
f = x / (10^expt)
if (round) {
if (f < 1.5) nf = 1
else if (f < 3) nf = 2
else if (f < 7) nf = 5
else nf = 10
}
else {
if (f <= 1) nf = 1
else if (f <= 2) nf = 2
else if (f <= 5) nf = 5
else nf = 10
}
return(nf * 10^expt)
}
end
EDIT
If you go
sysuse auto, clear
summarize turn, meanonly
local max = r(max)
scatter turn displacement, yla(0(10)`max', ang(h))
scatter turn displacement, yla(0(20)`max', ang(h))
you get good solutions. Clearly in this case we need to know that 10 or 20 is a step size to use. There would be scope to calculate a good width programmatically using your own recipe.
EDIT 10 May 2022
A revised and documented nicelabels is now downloadable from SSC.
I'm trying to implement merge sort using python 3.7. For that I've written a merge() function and a recursive sort() function. Here sort() function breaks a list until it has one element. But the problem is the interpreter cannot recognize the arguments m and n of the merge function as lists and hence showing the following error:
def merge(m, n):
x = y = 0
v = []
while x < len(m) and y < len(n):
if m[x] < n[y]:
v.append(m[x])
x = x + 1
elif m[x] > n[y]:
v.append(n[y])
y = y + 1
else:
v.append(m[x])
x, y = x + 1, y + 1
while x < len(m):
v.append(m[x])
x = x + 1
while y < len(n):
v.append(n[y])
y = y + 1
return v
def sort(a):
if len(a) == 1:
return a
else:
merge(sort(a[:len(a) // 2]), sort(a[len(a) // 2:]))
x = list(range(10, 0, -1))
sort(x)
print(x)
Expected result id the sorted list.
But python is showing this error:
Traceback (most recent call last):
File "", line 1, in
sort(x)
File "", line 5, in sort
merge(sort(a[:len(a) // 2]), sort(a[len(a) // 2:]))
File "", line 5, in sort
merge(sort(a[:len(a) // 2]), sort(a[len(a) // 2:]))
File "", line 5, in sort
merge(sort(a[:len(a) // 2]), sort(a[len(a) // 2:]))
File "", line 4, in merge
while x < len(m) and y < len(n):
TypeError: object of type 'NoneType' has no len()
The point is that your sort function does return a if len(a) == 1 but does not return anything if len(a) != 1. It should be return merge(…) instead of just merge(…) in the else part of your sort.
Fixes noted in comments. As an alternative, a one time allocation of a working array could be done and the merge sort would just use indexing as opposed to making multiple copies of the array.
def merge(m, n):
x = y = 0
v = []
while x < len(m) and y < len(n):
if m[x] <= n[y]: # fix
v.append(m[x])
x = x + 1
else:
v.append(n[y])
y = y + 1
while x < len(m):
v.append(m[x])
x = x + 1
while y < len(n):
v.append(n[y])
y = y + 1
return(v)
def sort(a):
if len(a) == 1:
return(a)
else:
return(merge(sort(a[:(len(a)//2)]), sort(a[len(a)//2:])))
# test sort
x = list(range(10, 0, -1))
x = sort(x) # fix
print(x)
Given a file that contains something like this:
1 2 3 4
5 6 7 8
a b c d
e f g h
Is there any unix command that I could use to circular shift the rows and coluns?
I am looking for something like say,
circular_shift -r 2 <file> (shift row by 2) to give :
a b c d
e f g h
1 2 3 4
5 6 7 8
and
circular_shift -c 2 <file> (shift column by 2) to give :
3 4 1 2
7 8 5 6
c d a b
g h e f
Thanks!
Using awk for row shift processing the file twice:
$ awk -v r=2 'NR==FNR && FNR>r || NR>FNR && FNR<=r' file file
a b c d
e f g h
1 2 3 4
5 6 7 8
Basically it prints records where NR > r on the first go and NR <= r on the second.
Edit: Version regarding records and fields:
$ awk -v r=1 -v c=1 '
NR==FNR && FNR>r || NR>FNR && FNR<=r {
j=0;
for(i=c+1;++j<=NF;i=(i<NF?i+1:1)){
printf "%s%s",$i,(i==c?ORS:OFS)
}
}
' foo foo
6 7 8 5
b c d a
f g h e
2 3 4 1
(Pretty much untested as I'm in a meeting... it fails at least for c=0)
Another solution using multidimensional arrays in gawk
circular_shift.awk
{for(i=1; i<=NF; ++i){d[NR][i]=$i}}
END{
c=c%NF; r=r%NR
for(i=1; i<=NR; ++i){
nr = i + (i>r?0:NR) - r
for(j=1; j<=NF; ++j){
nc = j + (j>c?0:NF) - c
printf d[nr][nc] (j!=NF?OFS:RS)
}
}
}
awk -vr=2 -f circular_shift.awk file
a b c d
e f g h
1 2 3 4
5 6 7 8
awk -vc=2 -f circular_shift.awk file
3 4 1 2
7 8 5 6
c d a b
g h e f
awk -vr=2 -vc=2 -f circular_shift.awk file
c d a b
g h e f
3 4 1 2
7 8 5 6
Shifting Rows
You can use head, tail and the shell:
function circular_shift() {
n=$1
file=$2
tail -n +"$((n+1))" "$file"
head -n "$n" "$file"
}
Call the function like this:
circular_shift 2 <file>
One restriction. The above function just works for n <= nlines(file). If you want to get rid of that restriction you need to know the length of the file in advance and use the modulo operator:
function circular_shift() {
n=$1
file=$2
len="$(wc -l "$file"|cut -d" " -f1)"
n=$((n%len))
tail -n +"$((n+1))" "$file"
head -n "$n" "$file"
}
Now try to call:
circular_shift 6 <file>
Shifting Columns
For the column shift I would use awk:
column-shift.awk
{
n = n % NF
c = 1
for(i=NF-n+1; i<=NF; i++) {
a[c++] = $i
}
for(i=1; i<NF-n+1; i++) {
a[c++] = $i
}
for(i=1; i<c; i++) {
$i = a[i]
}
}
print
Wrap it in a shell function:
function column_shift() {
n="$1"
file="$2"
awk -v n="$n" -f column-shift.awk "$file"
}
#Vivek V K, Try:
For moving the rows to a number up-wards.
awk -vcount=2 'NR>count{print;next} NR<=count{Q=Q?Q ORS $0:$0} END{print Q}' Input_file
For shifting the fields, could you please try following:
awk -vcount=2 '{for(i=count+1;i<=NF;i++){Q=Q?Q FS $i:$i};for(j=1;j<=count;j++){P=P?P FS $j:$j};print Q FS P;Q=P=""}' Input_file
awk -v C=$1 -v R=$2 '
function PrintReverse () {
if( ! R ) return
for( i=1; i>=0; i--) {
for( j=1; j<=R; j++) {
#print "DEBUG:: i: "i " j:" j " i * R + j :" i * R + j " lr:" lr
print L[ i * R + j ]
L[ i * R + j ] = ""
}
}
}
{
if( C ) {
# Reverse Column
for ( i=1; i<=NF; i+=2*C) {
for( j=0; j<C; j++) {
#print "DEBUG:: i: "i " j:" j " NF:" NF
tmp = $(i+j)
$(i+j) = $(i+j+C)
$(i+j+C) = tmp
}
}
$1=$1
}
if ( R ) {
# Line buffer
lr = ( FNR - 1 ) % ( R * 2 ) + 1
L[ lr] = $0
}
else print
}
lr >= ( R * 2) { PrintReverse() }
END { if( lr < ( R * 2 )) PrintReverse() }
' YourFile
Will do both your reverse action
R is the number of row, C the number of column to reverse.
using 2 loop (1 loop inside another one) [not the fastest but the more explicit for understanding the concept ion this case)
this is a buffer permutation for lines by loading line in a buffer of twice the number of Row and print 2 half content in reverse order
this is a field swap for column permutation, it cycle by 2 * number of column swaping field content with field with index + number of column
Row are treated after the buffer is feeded (in fact each R * 2 lines)
column are treated at each line
i add a test ( C ), ( ! R ), ... to allow single reverse (Row only or Column only)
So here is my situation. Ive been trying to make a advanced calculator in python 3.4, one where you can just type something like this. '1 + 1', and it would then give you the answer of '2'. Now i will explain how my calculator is supposed to work. So you start by entering a maths equation, then it counts the words you entered based on the spaces. It does this so it knows how long some future loops need to be. Then it splits up everything that you entered. It splits it up into str's and int's but its all still in the same variable and it's all still in order. The thing i'm having trouble with is when it is meant to actually do the calculations.
here is all of my code-
# This is the part were they enter the maths equation
print("-------------------------")
print("Enter the maths equation")
user_input = input("Equation: ")
# This is were it counts all of the words
data_count = user_input.split(" ")
count = data_count.__len__()
# Here is were is splits it into str's and int's
n1 = 0
data = []
if n1 <= count:
for x in user_input.split():
try:
data.append(int(x))
except ValueError:
data.append(x)
n1 += 1
# And this is were it actually calculates everything
number1 = 0
number2 = 0
n1 = 0
x = 0
answer = 0
while n1 <= count:
#The code below checks if it is a number
if data[n1] < 0 or data[n1] > 0:
if x == 0:
number1 = data[n1]
elif x == 1:
number2 = data[n1]
elif data[n1] is "+":
if x == 0:
answer += number1
elif x == 1:
answer += number2
n1 += 1
x += 1
if x > 1:
x = 0
print("Answer =", answer)
but during the calculation it messes up and gives me and error
error-
if data[n1] < 0 or data[n1] > 0:
TypeError: unorderable types: str() < int()
can anyone see what i am doing wrong here?
Thanks
When you are comparing a string and an integer, this problem comes.
Python doesn't guess, it throws an error.
To fix this, simply call int() to convert your string to an integer:
int(input(...))
So, corrected statement should be:
if int(data[n1]) < 0 or int(data[n1]) > 0:
i would like to write a simple line of code, without resorting to if statements, that would evaluate whether a number is within a certain range. i can evaluate from 0 - Max by using the modulus.
30 % 90 = 30 //great
however, if the test number is greater than the maximum, using modulus will simply start it at 0 for the remaining, where as i would like to limit it to the maximum if it's past the maximum
94 % 90 = 4 //i would like answer to be 90
it becomes even more complicated, to me anyway, if i introduce a minimum for the range. for example:
minimum = 10
maximum = 90
therefore, any number i evaluate should be either within range, or the minimum value if it's below range and the maximum value if it's above range
-76 should be 10
2 should be 10
30 should be 30
89 should be 89
98 should be 90
23553 should be 90
is it possible to evaluate this with one line of code without using if statements?
Probably the simplest way is to use whatever max and min are available in your language like this:
max(10, min(number, 90))
In some languages, e.g. Java, JavaScript, and C# (and probably others) max and min are static methods of the Math class.
I've used a clip function to make it easier (this is in JavaScript):
function clip(min, number, max) {
return Math.max(min, Math.min(number, max));
}
simple, but still branches even though if is not used:
r = ( x < minimum ) ? minimum : ( x > maximum ) ? maximum : x;
from bit twiddling hacks, assuming (2<3) == 1:
r = y ^ ((x ^ y) & -(x < y)); // min(x, y)
r = x ^ ((x ^ y) & -(x < y)); // max(x, y)
putting it together, assuming min < max:
r = min^(((max^((x^max)&-(max<x)))^min)&-(x<min));
how it works when x<y:
r = y ^ ((x ^ y) & -(x < y));
r = y ^ ((x ^ y) & -(1)); // x<y == 1
r = y ^ ((x ^ y) & ~0); // -1 == ~0
r = y ^ (x ^ y); // (x^y) & ~0 == (x^y)
r = y ^ x ^ y; // y^y == 0
r = x;
otherwise:
r = y ^ ((x ^ y) & -(x < y));
r = y ^ ((x ^ y) & -(0)); // x<y == 0
r = y ^ ((x ^ y) & 0); // -0 == 0
r = y; // (x^y) & 0 == 0
If you are using a language that has a ternary operator (such as C or Java), you could do it like this:
t < lo ? lo : (t > hi ? hi : t)
where t is the test variable, and lo and hi are the limits. That satisfies your constraints, in that it doesn't strictly use if-statements, but the ternary operator is really just syntactic sugar for an if-statement.
Using C/C++:
value = min*(number < min) +
max*(number > max) +
(number <= max && number >= min)*number%max;
The following is a brief explanation. Note that the code depends on 2 important issues to work correctly. First, in C/C++ a boolean expression can be converted to an integer. Second, the reminder of a negative number is the number it self. So, it is not the mathematical definition of the remainder. I am not sure if this is defined by the C/C++ standards or it is left to the implementation. Basically:
if number < min then:
value = min*1 +
max*0 +
0*number%max;
else if number > max
value = min*0 +
max*1 +
0*number%max;
else
value = min*1 +
max*1 +
1*number%max;
I don't see how you could...
(X / 10) < 1 ? 10 : (X / 90 > 1 ? 90 : X)
Number divided by 10 is less than 1? set to 10
Else
If number divided by 90 is greater than 90, set to 90
Else
set to X
Note that it's still hidden ifs. :(