मेल खाने वाले फ़ील्ड के आधार पर कॉलम की जोड़ी


11

मेरे पास निम्न प्रारूप में एक बड़ी फ़ाइल है:

2 1019 0 12 
2 1019 3 0 
2 1021 0 2 
2 1021 2 0 
2 1022 4 5
2 1030 0 1 
2 1030 5 0 
2 1031 4 4

यदि स्तंभ 2 में मान मेल खाते हैं, तो मैं दोनों रेखाओं के स्तंभ 3 और 4 में मानों को जोड़ना चाहता हूं , और केवल अद्वितीय पंक्ति में मानों का योग।

इसलिए मैं जिस आउटपुट की उम्मीद कर रहा हूं वह इस तरह दिखेगा:

2 1019 15 
2 1021 4 
2 1022 9 
2 1030 6 
2 1031 8

मैं के अनुसार फ़ाइलें क्रमबद्ध करने में सक्षम हूँ स्तंभ 2 के साथ awkया sortऔर के साथ पिछले कॉलम योग awkहै, लेकिन केवल व्यक्तिगत लाइनों के लिए दो पंक्तियों जहां के लिए नहीं कॉलम 2 मैचों।


1
कॉलम 1 के बारे में क्या?
ग्लेन जैकमैन

@glennjackman: कॉलम 1 में प्रत्येक फ़ाइल के लिए समान मूल्य है। यह फ़ाइल के लिए एक पहचानकर्ता के रूप में कार्य करता है (मेरे पास उनमें से 45 हैं) और इसका उपयोग कुछ डाउनस्ट्रीम प्रक्रिया के लिए किया जाएगा। मेरे प्रश्न के लिए इसे नजरअंदाज (या हटा दिया गया) किया जा सकता है और बाद में फिर से जोड़ा जा सकता है।
टॉमपियो

या, $1 $2कुंजी के रूप में बनाते हैं ।
ग्लेन जैकमैन

जवाबों:


12

मैं पर्ल में ऐसा करूंगा:

$ perl -lane '$k{"$F[0] $F[1]"}+=$F[2]+$F[3]; 
              END{print "$_ $k{$_}" for keys(%k) }' file 
2 1019 15
2 1021 4
2 1030 6
2 1031 8
2 1022 9

या जाग:

awk '{a[$1" "$2]+=$3+$4}END{for (i in a){print i,a[i]}}' file 

यदि आप चाहते हैं कि दूसरे स्तंभ के अनुसार छांटे गए आउटपुट को आप केवल पाइप कर सकें sort:

awk '{a[$1" "$2]+=$3+$4}END{for (i in a){print i,a[i]}}' file | sort -k2

ध्यान दें कि दोनों समाधानों में 1 कॉलम भी शामिल है। विचार पहले और दूसरे स्तंभों को एक हैश (पर्ल में) या एक सहयोगी सरणी (awk में) के रूप में उपयोग करने के लिए है। प्रत्येक समाधान में कुंजी column1 column2इसलिए है कि यदि दो पंक्तियों में एक ही कॉलम दो हैं, लेकिन एक अलग कॉलम एक है, तो उन्हें अलग से समूहीकृत किया जाएगा:

$ cat file
2 1019 2 3
2 1019 4 1
3 1019 2 2

$ awk '{a[$1" "$2]+=$3+$4}END{for (i in a){print i,a[i]}}' file
3 1019 4
2 1019 10

7

शायद यह मदद कर सकता है, लेकिन कॉलम 1 हमेशा 2 है और क्या परिणाम इस पर निर्भर करता है?

awk '{ map[$2] += $3 + $4; } END { for (i in map) { print "2", i, map[i] | "sort -t't'" } }' file

या छँटाई के बारे में टिप्पणियों में ग्लेन जैकमैन द्वारा उल्लिखित :

gawk '{ map[$2] += $3 + $4; } END { PROCINFO["sorted_in"] = "@ind_str_asc"; for (i in map) { print 2, i, map[i] } }' file

2
यदि आपके पास जीएनयू जाग है, तो PROCINFO["sorted_in"] = "@ind_num_asc"पाइपिंग के बजाय का उपयोग करें sort। रेफ gnu.org/software/gawk/manual/html_node/…
ग्लेन जैकमैन

@taliezin: धन्यवाद taliezin और टेरडॉन। दोनों दृष्टिकोण एक आकर्षण की तरह काम करते थे। तुम्हारी मदद के लिए शुक्रिया।
टॉमपियो

1
@ पेटीज़िन: जैसा कि मैंने कहा कि दोनों ने मेरे लिए काम किया, मैंने टेर्डन के उत्तरों को "सही" के रूप में चिह्नित किया। मुझे लगता है कि आप क्या करना चाहते हैं। एक बार फिर धन्यवाद।
टॉमपियो

1
यदि मैं आपके द्वारा बताई गई प्रश्न को समझना चाहता हूं, तो हम केवल एक काउंटर जोड़ सकते हैं और उसे प्रिंट कर सकते हैं: awk '{map [$ 2] + = $ 3 + $ 4; } END {के लिए (मैं मानचित्र में) {प्रिंट "2", मैं, मानचित्र [i] | "सॉर्ट -t'n '"; cnt ++; } प्रिंट "कुल अद्वितीय:" cnt} 'फ़ाइल
taliezin

1
यह लगभग समान है: awk '{map [$ 2] + = $ 3 + $ 4; OC [$ 2] ++; } END {के लिए (मैं मानचित्र में) {प्रिंट "2", मैं, मानचित्र [i], महासागर [i] | "सॉर्ट -t'n '"; }} ', अब आप घटनाओं के साथ एक और कॉलम देखेंगे।
तालीज़ीन

4

आप डेटा को पूर्व-सॉर्ट कर सकते हैं और awk को विवरणों को संभालने दें:

sort -n infile | awk 'NR>1 && p!=$2 {print p,s} {s+=$3+$4} {p=$2}'

आप संचायक को रीसेट करना चाहते हैं:

sort -n infile | awk 'NR>1 && p!=$2 {print p,s;s=0} {s+=$3+$4} {p=$2}'

आउटपुट:

1019 15
1021 19
1022 28
1030 34

यदि आप वास्तव में पहला कॉलम रखना चाहते हैं, तो कुछ इस तरह से करें:

sort -n infile | awk 'NR>1 && p!=$1FS$2 {print p,s} {s+=$3+$4} {p=$1FS$2}'

आउटपुट:

2 1019 15
2 1021 19
2 1022 28
2 1030 34

व्याख्या

pचर धारण $2पिछली लाइन के मूल्य, या $1FS$2इसके बाद के संस्करण दूसरे मामले में। इसका मतलब यह है कि पिछली लाइन के चालू लाइन ( ) के समान नहीं {print p,s}होने पर ट्रिगर होता $2है p!=$2


ध्यान दें कि भले ही पहले कॉलम में अलग-अलग मूल्य हों sort -k2जिन्हें आप दूसरे कॉलम द्वारा सॉर्ट करने के लिए उपयोग कर सकते हैं
gaoithe

2

स्विस सेना चाकू का उपयोग करना mlr:

mlr --nidx   put '$5=$3+$4'   then   stats1 -g 1,2 -f 5 -a sum   infile

आउटपुट:

2   1019    15
2   1021    4
2   1022    9
2   1030    6
2   1031    8

टिप्पणियाँ:

  • --nidxmlrसंख्यात्मक क्षेत्र के नाम का उपयोग करना बताता है।

  • put '$5=$3+$4'एक नया 5 वां फ़ील्ड बनाता है , फ़ील्ड 3 और 4 का योग ।

  • stats1समारोह (या " क्रिया ") एक छोटे स्विस सेना चाकू है
    की अधिक से अधिक स्विस सेना चाकू के भीतर mlr, इस तरह के रूप में कई संचायक आधारित कार्यों के साथ sum, count, mean, आदि

    stats1 -g 1,2कॉलम 1 और 2 द्वारा डेटा को समूहित करता है , और -f 5 -a sumफिर उन समूहों के फ़ील्ड 5 को जोड़ता है । stats1 केवल खेतों के नाम।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.