Calculate average of top n% of values - UNIX


 
Thread Tools Search this Thread
Top Forums Shell Programming and Scripting Calculate average of top n% of values - UNIX
# 1  
Old 05-20-2014
Calculate average of top n% of values - UNIX

Hey guys,

I have several huge tab delimited files which look like this:
Code:
a 1 20
a 3 15
a 5 10
b 2 15
b 6 10
c 3 23

what I am interested is to calculate the average of top n% of data in third column. So for example for this file the top 50% values are:
Code:
23
20

(Please note that it is not top 50% of the number of inputs, it's top 50% of values. Basically repetitions are ignored)
And then the average (the output) will be:
Code:
21.5

I can do it with making 2 temporary files for each input file which is dumber even than the most possible stupid way! :|

I appreciate if you have something neat and clean on your mind for this.
Thanks in advance!
# 2  
Old 05-20-2014
Code:
gawk -v p=50 '{a[$3]}END{asorti(a,as);l=length(a);for(i=l;(i/l)*100>p;i--) print as[i]}' myFile

# 3  
Old 05-20-2014
Thanks for your reply vgersh99!

It has some problems
First of all it does not do the sorting properly. Here is what I got for top 0.1% for example:
Code:
258
2575
257
2553
255
251
25
...

apparently it sort them like text.

Also I would like to have the average of all these numbers (current output) as thefinal output.

I also tried to make it automatic for many files like below, it did not work!
Code:
for file in *.txt do; gawk -v p=50 '{a[$3]}END{asorti(a,as);l=length(a);for(i=l;(i/l)*100>p;i--) print as[i]}' $file; done

Thanks 1000 times for your time.
# 4  
Old 05-20-2014
What's your longest number?

Here is a update with assumption of 7 or less digits (adjust red value as you need):

Code:
gawk -v p=50 '{a[sprintf("%07d",$3)]}
  END{asorti(a,as);l=length(a);for(i=l;(i/l)*100>p;i--)
  t+=as[i]; printf "%.2f\n", t/l/2}' infile

For multi files:

Code:
for file in *.txt
do
   gawk -v p=50 '
   {a[sprintf("%07d",$3)]}
   END{
      asorti(a,as)
      l=length(a)
      for(i=l;(i/l)*100>p;i--) t+=as[i]
      printf "%s\t%.2f\n", FILENAME, t/l/2}' "$file"
done

# 5  
Old 05-21-2014
Quote:
I can do it with making 2 temporary files for each input file which is dumber even than the most possible stupid way! :|
What way have you tried?

Can you send the output from one command straight into the next, a bit like this?:-
Code:
cut -f3 -d " " input_file | sort -unr | ........

It would probably be more beneficial if it is in the tools that you are most comfortable with rather than a bespoke one-off that you dare not adjust.

What suits you?


Robin
# 6  
Old 05-21-2014
Quote:
What's your longest number?

Here is a update with assumption of 7 or less digits (adjust red value as you need):


Code:
gawk -v p=50 '{a[sprintf("%07d",$3)]}
END{asorti(a,as);l=length(a);for(i=l;(i/l)*100>p;i--)
t+=as[i]; printf "%.2f\n", t/l/2}' infile

For multi files:


Code:
for file in *.txt
do
gawk -v p=50 '
{a[sprintf("%07d",$3)]}
END{
asorti(a,as)
l=length(a)
for(i=l;(i/l)*100>p;i--) t+=as[i]
printf "%s\t%.2f\n", FILENAME, t/l/2}' "$file"
done
I don't think I have more than 7 digits. I tried it with two following sample files:
file1.txt
Code:
chr2L	10	23
chr2L	20	20
chr2L	35	15
chr2L	36	10
chr3R	12	10
chrX	10	15

file2.txt
Code:
chr2L	10	230
chr2L	20	20
chr2L	35	1.5
chr2L	36	1000
chr3R	12	100
chr3R	20	300
chrX	10	15
chrX	26	1500

and this is what I got as output when p=50:
Code:
file1.txt 21.50
file2.txt 1515.00

I think something is wrong but I don't know what! For sure the average of top 50% (1515 for second file) cannot be more than the maximum(1500)!!

I also tried it with different percentages. (p=12.5,p=10,...) but it does not seem to work properly. my desired percentage is p=0.1 if that is important to know.

Thanks once again for helping me.

---------- Post updated at 12:18 PM ---------- Previous update was at 12:10 PM ----------

Quote:
It would probably be more beneficial if it is in the tools that you are most comfortable with rather than a bespoke one-off that you dare not adjust.
Dear rbatte1,

You are absolutely right with no doubt!
I am a student in "bioinformatics" and my knowledge in programming is sub zero which is a shame. you asked what I did. What I could think of was to extract the third column first and using 'pipe' sort it numerically and then again use pipe to have only unique values and then sort them again and count the numbers of values take 0.1% of them and another pipe and then the average function!!
you see how stupid one can be!!
But even for each step of this dumb way I have to Google and such simple script takes me a half a day or more to complete! and this is part of a huge analysis of-course...

Now you see why I decided to ask for help! :|

Kindest regards,
aman
# 7  
Old 05-21-2014
We're always happy to have questions & I've learned lots from this site by asking what many consider as daft questions. Hopefully this helps you understand and become better, but it sometimes helps us who know a bit to have problems to solve. We all contribute and see different ways of doing things.

If you make an effort, folks here are happy to help - and I've learned lots of new things. Most people will have joined to ask a question in the first place, so you are most welcome.

Whatever suits you best is a good way to steer us. Some tools like awk and their variants can take years to get a good understanding on. I'm still struggling along trying to learn, so don't get disheartened.

If you have a go, then show what you've done when asking for help the collective group will no doubt help you out.



Regards,
Robin
Login or Register to Ask a Question

Previous Thread | Next Thread

8 More Discussions You Might Find Interesting

1. UNIX for Beginners Questions & Answers

Calculate average from a given set of keys and values

Hello, I am writing a script which expects as its input a hash with student names as the keys and marks as the values. The script then returns array of average marks for student scored 60-70, 70-80, and over 90. Output expected 50-70 1 70-90 3 over 90 0 The test script so far... (4 Replies)
Discussion started by: nans
4 Replies

2. Shell Programming and Scripting

Calculate the average per block.

My old school way is a one liner. And will search for average from SAR, to get the data receive rate. But, I dont think it is practical or accurate,. Because it calculates to off peak hours. I am planning to change it. My cron runs every 30 mins. When my cron runs, and my time is 14:47pm,, it will... (1 Reply)
Discussion started by: invinzin21
1 Replies

3. Shell Programming and Scripting

Calculate average, azimut and distance

Gents, Please i will to get the distance and azimut from 2 coordinates: Usig excel formula i get the correct values, but i will like to do it using awk. Example A 35089.0 50345.016 9 75 1 2101774 77 70 79 483911.6 2380106.9 137.4 1 1 6 1 A 35089.0 50345.01620 75... (8 Replies)
Discussion started by: jiam912
8 Replies

4. Shell Programming and Scripting

Calculate Average AWK

I want to calculate the average line by line of some files with several lines on them, the files are identical, just want to average the 3rd columns of those files.:wall: Example file: File 1 001 0.046 0.667267 001 0.047 0.672028 001 0.048 0.656025 001 0.049 ... (2 Replies)
Discussion started by: AriasFco
2 Replies

5. Shell Programming and Scripting

AWK novice - calculate the average

Hi, I have the following data in a file for example: P1 XXXXXXX.1 YYYYYYY.1 ZZZ.1 P1 XXXXXXX.2 YYYYYYY.2 ZZZ.2 P1 XXXXXXX.3 YYYYYYY.3 ZZZ.3 P1 XXXXXXX.4 YYYYYYY.4 ZZZ.4 P1 XXXXXXX.5 YYYYYYY.5 ZZZ.5 P1 XXXXXXX.6 YYYYYYY.6 ZZZ.6 P1 XXXXXXX.7 YYYYYYY.7 ZZZ.7 P1 XXXXXXX.8 YYYYYYY.8 ZZZ.8 P2... (6 Replies)
Discussion started by: alex2005
6 Replies

6. Shell Programming and Scripting

Calculate average time using a script

Hello, I'm hoping to get some help on calculating an average time from a list of times (hour:minute:second). Here's what my list looks like right now, it will grow (I can get the full date or change the formatting of this as well): 07:55:31 09:42:00 08:09:02 09:15:23 09:27:45 09:49:26... (4 Replies)
Discussion started by: jaredhanks
4 Replies

7. Programming

calculate average

I have a file which is 2 3 4 5 6 6 so i am writing program in C to calculate mean.. #include<stdio.h> #include<string.h> #include <math.h> double CALL mean(int n , double x) main (int argc, char **argv) { char Buf,SEQ; int i; double result = 0; FILE *fp; (3 Replies)
Discussion started by: cdfd123
3 Replies

8. UNIX for Dummies Questions & Answers

calculate average of column 2

Hi I have fakebook.csv as following: F1(current date) F2(popularity) F3(name of book) F4(release date of book) 2006-06-21,6860,"Harry Potter",2006-12-31 2006-06-22,,"Harry Potter",2006-12-31 2006-06-23,7120,"Harry Potter",2006-12-31 2006-06-24,,"Harry Potter",2006-12-31... (0 Replies)
Discussion started by: onthetopo
0 Replies
Login or Register to Ask a Question