LinuxQuestions.org
Help answer threads with 0 replies.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 11-06-2018, 07:05 AM   #1
Bartonsen
Member
 
Registered: Oct 2016
Posts: 41

Rep: Reputation: Disabled
Sum each column using awk


With this $InFile:
Code:
201810;Edwin;51;44;35;84;65;88;45;42;24;61;36;110;88;50;49;21;22;45;34;103;46;22;18;25;19;115;67;44;26;19;15
201810;Edwin;67;68;54;55;29;94;58;43;20;66;58;26;42;24;29;21;7;29;20;52;22;22;19;19;16;54;14;41;22;23;17
201810;Edwin;106;103;117;153;158;53;73;60;63;89;62;59;69;50;38;29;30;33;27;87;81;45;45;46;29;101;104;52;54;33;42
201810;Jimmy;72;43;88;58;128;100;65;31;56;34;77;49;76;58;33;19;31;24;161;76;59;36;18;18;65;45;42;30;23;17;38
201810;Jimmy;52;37;78;28;57;69;44;23;77;55;37;57;36;44;26;15;17;9;58;30;31;25;18;17;24;23;29;14;17;21;18
201810;Jimmy;124;123;186;158;143;174;97;121;113;79;165;139;114;103;68;70;96;72;140;105;83;86;73;47;105;111;107;98;35;46;77
201810;Pearl;10;27;44;21;49;47;46;13;7;25;15;32;65;49;8;11;25;13;22;31;30;5;14;18;9;18;10;28;8;20;12
201810;Pearl;75;83;119;124;115;133;172;48;70;68;85;98;107;139;51;67;88;79;112;110;133;61;50;63;77;81;75;143;36;64;77
201810;Pearl;23;32;18;22;28;9;27;28;28;23;23;25;13;27;31;40;32;38;38;23;40;35;45;44;38;30;14;37;32;49;38
201811;Edwin;94;33;56;54;28;4;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0
201811;Edwin;37;20;42;24;29;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0
201811;Edwin;73;68;102;96;50;2;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0
201811;Jimmy;27;150;84;58;49;3;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0
201811;Jimmy;13;67;28;33;16;2;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0
201811;Jimmy;55;133;137;127;110;2;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0
201811;Pearl;18;19;10;33;3;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0
201811;Pearl;74;85;45;133;34;15;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0
201811;Pearl;40;30;20;39;33;7;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0
How can I produce this $OutFile?
Code:
201810;Edwin;224;215;206;292;252;235;176;145;107;216;156;195;199;124;116;71;59;107;81;242;149;89;82;90;64;270;185;137;102;75;74
201810;Jimmy;248;203;352;244;328;343;206;175;246;168;279;245;226;205;127;104;144;105;359;211;173;147;109;82;194;179;178;142;75;84;133
201810;Pearl;108;142;181;167;192;189;245;89;105;116;123;155;185;215;90;118;145;130;172;164;203;101;109;125;124;129;99;208;76;133;127
201811;Edwin;204;121;200;174;107;6;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0
201811;Jimmy;95;350;249;218;175;7;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0
201811;Pearl;132;134;75;205;70;22;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0
In $InFile, each person has 1 or more entries per month. I want to sum each column starting from column 3, so that each person has only one entry per month.
 
Old 11-06-2018, 07:33 AM   #2
BW-userx
LQ Guru
 
Registered: Sep 2013
Location: Somewhere in my head.
Distribution: Slackware (15 current), Slack15, Ubuntu studio, MX Linux, FreeBSD 13.1, WIn10
Posts: 10,342

Rep: Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242
if you where to search this sight/forum you're bound to find your answer in here already hashed out and gone over many times. as, I've seen this question before.

BIG HINT:
just use your title of your post for the search pattern in this forums search.

Last edited by BW-userx; 11-06-2018 at 07:35 AM.
 
Old 11-06-2018, 07:55 AM   #3
l0f4r0
Member
 
Registered: Jul 2018
Location: Paris
Distribution: Debian
Posts: 900

Rep: Reputation: 290Reputation: 290Reputation: 290
It's probably not optimized but here is one of multiple solutions:

Code:
awk '
	BEGIN
		{
		FS=OFS=";"
		} 
	
	{
	if((date=="" && name=="")||($1 == date && $2 == name)) 
		{ 
		date=$1; name=$2; for(i=3;i<=NF;i++){sum[i]+=$i;}
		} 
	else 
		{
		printf "%s;%s;",date,name; date=$1; name=$2; 
		for(value in sum){printf "%d;",sum[value];sum[value]=""}
		printf "\n"; 
		for(i=3;i<=NF;i++){sum[i]+=$i;}} 
		}
	
	END
		{
		printf "%s;%s;",date,name;  for(value in sum){printf "%d;",sum[value]}
		}
		
	' input.txt
EDIT: yes, as said by BW-userx, there are already a lot of LQ threads about awk/sum and so on... So you have already all the material/logic you need in the history...

Last edited by l0f4r0; 11-06-2018 at 07:58 AM.
 
Old 11-06-2018, 05:11 PM   #4
syg00
LQ Veteran
 
Registered: Aug 2003
Location: Australia
Distribution: Lots ...
Posts: 21,128

Rep: Reputation: 4121Reputation: 4121Reputation: 4121Reputation: 4121Reputation: 4121Reputation: 4121Reputation: 4121Reputation: 4121Reputation: 4121Reputation: 4121Reputation: 4121
That's using awk like it was a traditional language - I am quite taken by associative arrays having come by them late in my programming experience. I would prefer something like this.
Code:
{for(i=3;i<=NF;i++){sum[$1";"$2][i]+=$i}}
No need to worry about the testing.
In the END block the key can be printed to get the first 2 fields ...

Gotta love the flexibility.
 
Old 11-06-2018, 05:41 PM   #5
danielbmartin
Senior Member
 
Registered: Apr 2010
Location: Apex, NC, USA
Distribution: Mint 17.3
Posts: 1,881

Rep: Reputation: 660Reputation: 660Reputation: 660Reputation: 660Reputation: 660Reputation: 660
Quote:
Originally Posted by syg00 View Post
... I am quite taken by associative arrays ...
Gotta love the flexibility.
With this InFile ...
Code:
201810;Edwin;51;44;35;84;65;88;45;42;24;61;36;110;88;50;49;21;22;45;34;103;46;22;18;25;19;115;67;44;26;19;15
201810;Edwin;67;68;54;55;29;94;58;43;20;66;58;26;42;24;29;21;7;29;20;52;22;22;19;19;16;54;14;41;22;23;17
201810;Edwin;106;103;117;153;158;53;73;60;63;89;62;59;69;50;38;29;30;33;27;87;81;45;45;46;29;101;104;52;54;33;42
201810;Jimmy;72;43;88;58;128;100;65;31;56;34;77;49;76;58;33;19;31;24;161;76;59;36;18;18;65;45;42;30;23;17;38
201810;Jimmy;52;37;78;28;57;69;44;23;77;55;37;57;36;44;26;15;17;9;58;30;31;25;18;17;24;23;29;14;17;21;18
201810;Jimmy;124;123;186;158;143;174;97;121;113;79;165;139;114;103;68;70;96;72;140;105;83;86;73;47;105;111;107;98;35;46;77
201810;Pearl;10;27;44;21;49;47;46;13;7;25;15;32;65;49;8;11;25;13;22;31;30;5;14;18;9;18;10;28;8;20;12
201810;Pearl;75;83;119;124;115;133;172;48;70;68;85;98;107;139;51;67;88;79;112;110;133;61;50;63;77;81;75;143;36;64;77
201810;Pearl;23;32;18;22;28;9;27;28;28;23;23;25;13;27;31;40;32;38;38;23;40;35;45;44;38;30;14;37;32;49;38
201811;Edwin;94;33;56;54;28;4;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0
201811;Edwin;37;20;42;24;29;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0
201811;Edwin;73;68;102;96;50;2;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0
201811;Jimmy;27;150;84;58;49;3;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0
201811;Jimmy;13;67;28;33;16;2;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0
201811;Jimmy;55;133;137;127;110;2;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0
201811;Pearl;18;19;10;33;3;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0
201811;Pearl;74;85;45;133;34;15;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0
201811;Pearl;40;30;20;39;33;7;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0
... this annotated awk ...
Code:
awk -F ";" \
  '{RowDes=$01 FS $02;
# Build an array of unique Row Designators.
# A Row Designator is of the form yyyymm;PersonalName
# For example: 201810;Edwin
    RowDesList[RowDes]=RowDes;
# Remember the field count of the longest InFile line.
    if (LongestLine<NF) LongestLine=NF
# Accumulate the Sums for each distinct row designator.
# Sum is a two-dimensional array.
    for (Month=3;Month<=NF;Month++) Sum[RowDes,Month]+=$Month}
# At this point all Sums have been calculated.
  END{nRows=asort(RowDesList);
      for (j=1;j<=nRows;j++)
# Each Output Line starts with a Row Designator.
        {RowDes=OL=RowDesList[j];
# Build the Output Line by appending the Sums one month at a time.
         for (Month=3;Month<=LongestLine;Month++)
          OL=OL FS Sum[RowDes,Month]
# Get rid of any trailing semicolons.
          gsub(/;*$/,"",OL)
# Print the Output Line.
          print OL}}' $InFile >$OutFile
... produced this OutFile ...
Code:
201810;Edwin;224;215;206;292;252;235;176;145;107;216;156;195;199;124;116;71;59;107;81;242;149;89;82;90;64;270;185;137;102;75;74
201810;Jimmy;248;203;352;244;328;343;206;175;246;168;279;245;226;205;127;104;144;105;359;211;173;147;109;82;194;179;178;142;75;84;133
201810;Pearl;108;142;181;167;192;189;245;89;105;116;123;155;185;215;90;118;145;130;172;164;203;101;109;125;124;129;99;208;76;133;127
201811;Edwin;204;121;200;174;107;6;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0
201811;Jimmy;95;350;249;218;175;7;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0
201811;Pearl;132;134;75;205;70;22;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0
Daniel B. Martin

.
 
Old 11-07-2018, 12:20 PM   #6
Bartonsen
Member
 
Registered: Oct 2016
Posts: 41

Original Poster
Rep: Reputation: Disabled
BW-userx: Thanks. I searched both this forum and others for days, without finding any good examples to use. But thanks for the tip!

l0f4r0: Thanks. I tried your code, but I found that it made wrong calculations... could't figure out what it actual calculated either...?

syg00: I guess your code could work if you want to add the total of columns 3++, but in my example I need the values based on columns 1 and 2 also.

danielbmartin! You are awesome! Thanks you so much! Your code is exactly what I needed!! And the explanations are great. That will help me to understand better what is going on.
 
Old 11-07-2018, 04:22 PM   #7
syg00
LQ Veteran
 
Registered: Aug 2003
Location: Australia
Distribution: Lots ...
Posts: 21,128

Rep: Reputation: 4121Reputation: 4121Reputation: 4121Reputation: 4121Reputation: 4121Reputation: 4121Reputation: 4121Reputation: 4121Reputation: 4121Reputation: 4121Reputation: 4121
It does work - read it again. And the note on END block.
 
Old 11-08-2018, 03:07 AM   #8
l0f4r0
Member
 
Registered: Jul 2018
Location: Paris
Distribution: Debian
Posts: 900

Rep: Reputation: 290Reputation: 290Reputation: 290
Quote:
Originally Posted by Bartonsen View Post
l0f4r0: Thanks. I tried your code, but I found that it made wrong calculations... could't figure out what it actual calculated either...?
It's weird because my output is exactly the same as the one you requested.

You requested:
Quote:
Originally Posted by Bartonsen View Post
How can I produce this $OutFile?
Code:
201810;Edwin;224;215;206;292;252;235;176;145;107;216;156;195;199;124;116;71;59;107;81;242;149;89;82;90;64;270;185;137;102;75;74
201810;Jimmy;248;203;352;244;328;343;206;175;246;168;279;245;226;205;127;104;144;105;359;211;173;147;109;82;194;179;178;142;75;84;133
201810;Pearl;108;142;181;167;192;189;245;89;105;116;123;155;185;215;90;118;145;130;172;164;203;101;109;125;124;129;99;208;76;133;127
201811;Edwin;204;121;200;174;107;6;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0
201811;Jimmy;95;350;249;218;175;7;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0
201811;Pearl;132;134;75;205;70;22;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0
I have:
Code:
$ awk -f awk_script.txt input.txt
201810;Edwin;224;215;206;292;252;235;176;145;107;216;156;195;199;124;116;71;59;107;81;242;149;89;82;90;64;270;185;137;102;75;74;
201810;Jimmy;248;203;352;244;328;343;206;175;246;168;279;245;226;205;127;104;144;105;359;211;173;147;109;82;194;179;178;142;75;84;133;
201810;Pearl;108;142;181;167;192;189;245;89;105;116;123;155;185;215;90;118;145;130;172;164;203;101;109;125;124;129;99;208;76;133;127;
201811;Edwin;204;121;200;174;107;6;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;
201811;Jimmy;95;350;249;218;175;7;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;
201811;Pearl;132;134;75;205;70;22;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;
With awk_script.txt (I've adapted the indentation very slightly):
Code:
BEGIN {
	FS=OFS=";"
	} 

	{
	if((date=="" && name=="")||($1 == date && $2 == name)) 
		{ 
		date=$1; name=$2; for(i=3;i<=NF;i++){sum[i]+=$i;}
		} 
	else 
		{
		printf "%s;%s;",date,name; date=$1; name=$2; 
		for(value in sum){printf "%d;",sum[value];sum[value]=""}
		printf "\n"; 
		for(i=3;i<=NF;i++){sum[i]+=$i;}
		} 
	}

END {
	printf "%s;%s;",date,name;  for(value in sum){printf "%d;",sum[value]}
	}
 
Old 01-10-2022, 08:54 AM   #9
shruggy
Senior Member
 
Registered: Mar 2020
Posts: 3,670

Rep: Reputation: Disabled
Just wanted to show how awesome Miller is. I'm deliberately using Miller 6 options here: Miller is now rewritten in Go, so trying out the latest release is a piece of cake.
Code:
mlr -cNM --fs \; --ragged stats1 -a sum --grfx '^[12]$'
 
1 members found this post helpful.
Old 01-10-2022, 01:56 PM   #10
sundialsvcs
LQ Guru
 
Registered: Feb 2004
Location: SE Tennessee, USA
Distribution: Gentoo, LFS
Posts: 10,659
Blog Entries: 4

Rep: Reputation: 3941Reputation: 3941Reputation: 3941Reputation: 3941Reputation: 3941Reputation: 3941Reputation: 3941Reputation: 3941Reputation: 3941Reputation: 3941Reputation: 3941
Another thought: many decades ago, a programmer named Larry Wall looked at "awk" and wasn't satisfied with what he saw. So, he did the inevitable thing: he invented an improved language and called it, "Perl." It was and still is very good at "doing complicated manipulations of really-big files." It still provides the reference implementation definition of "regular expressions." It also has a truly enormous contributed library of thoroughly-tested modules which test themselves on your hardware when you install them. Yet, its syntax and shortcuts will be very familiar to "awk" users.

Therefore – while "awk" is a very fine tool, there are today many tools available in your tool-box. Get to know several of them. Perl is only one.
 
1 members found this post helpful.
  


Reply

Tags
csv



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
[SOLVED] AWK - How to parse a Web log file to count column and the last occurrence of that column Alvin88 Linux - Newbie 10 06-23-2017 05:59 AM
[SOLVED] How to sum only specific column values in a row using awk? jv61 Linux - Newbie 3 01-17-2013 11:41 AM
[SOLVED] createing sum column udiubu Linux - Newbie 15 07-11-2012 01:11 PM
Sum a column micyew Programming 10 06-26-2012 02:30 PM
[PHP] Sum of a column by key kazuni Programming 4 11-09-2009 08:54 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 02:49 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration