การคำนวณค่าอัตราส่วนภายในบรรทัดที่มีเลขฐานสอง 0 และ 1

ฉันมีไฟล์ข้อมูลที่มีมากกว่า 2,000 บรรทัดและ 45,001 คอลัมน์

คอลัมน์แรกจริงๆ แล้วคือ "สตริง" ซึ่งอธิบายประเภทข้อมูล

เริ่มจากคอลัมน์ #2 จนถึงคอลัมน์ #45001 ข้อมูลจะแสดงเป็น

"1"

or

"0"

เช่น รูปแบบของข้อมูลในบรรทัดจะเป็น

(0 0 0 1 1 0 1 1 1 0 1 1 1 1 0 0 0 1 0 0 1 1 1 0 0)

จำนวนข้อมูลทั้งหมดคือ 25 ข้อมูล ภายในบรรทัดข้อมูลนี้มีกลุ่มย่อย 5 กลุ่มซึ่งสร้างด้วยตัวเลข "1" เท่านั้น เช่น (11 111 1111 1 111 ) "0" ที่อยู่ระหว่างกลุ่มย่อยจะถือว่าเป็น "ตัวคั่น" ผลรวมของ "1" ทั้งหมดคือ = 13

ผมอยากจะคำนวณอัตราส่วนของ

(ผลรวมของ "1" ทั้งหมด / จำนวนกลุ่มย่อยทั้งหมดที่สร้างโดย "1" เท่านั้น)

นั่นคือ

(13/5).

ฉันลองใช้รหัสนี้เพื่อคำนวณผลรวมของ "1" ทั้งหมด ;

awk -F '0' '{print NF}' < inputfile.in

จะได้ค่า 13

แต่ฉันไม่รู้ว่าจะต้องไปไกลกว่านี้เพื่อคำนวณอัตราส่วนที่ต้องการได้อย่างไร ฉันไม่รู้ว่าจะหาจำนวนกลุ่มย่อยในแต่ละบรรทัดได้อย่างไร เพราะจำนวนครั้งที่ "1" และ "0" เกิดขึ้นแบบสุ่ม

ต้องการความช่วยเหลือในการจัดเรียงปัญหานี้

ขอขอบคุณความช่วยเหลือใด ๆ ล่วงหน้า


person Vijay    schedule 15.03.2015    source แหล่งที่มา
comment
โพสต์อินพุตที่แน่นอน มีช่องว่างก่อนและหลังเลข ti หรือไม่?   -  person Avinash Raj    schedule 15.03.2015
comment
นี่คือข้อมูลตัวอย่าง [BMR_10@O24-BMR_6@O13-H13 1 1 1 1 1 1 1 1 0 1 1 1 1 0 1 1 1 1 1 1 1 0 1 1 1] คอลัมน์แรกเป็นสตริงและส่วนที่เหลือเป็นข้อมูลจากแถวเดียวเท่านั้น ฉันไม่สามารถแสดงไฟล์จริงได้เนื่องจากขนาดประมาณ 5MB   -  person Vijay    schedule 15.03.2015


คำตอบ (2)


คำอธิบายไม่ชัดเจนสำหรับฉันว่ารูปแบบของไฟล์อินพุตคืออะไร สมมติว่าอินพุตมีลักษณะดังนี้:

$ cat file
0 0 0 1 1 0 1 1 1 0 1 1 1 1 0 0 0 1 0 0 1 1 1 0 0

หากต้องการนับจำนวนและจำนวนกลุ่มและหาอัตราส่วน:

$ awk '{f=0;s1=0;s2=0;for (i=2;i<=NF;i++){s1+=$i;if ($i && !f)s2++;f=$i}; print s1/s2}' file
2.6

อัปเดต: การจัดการศูนย์ทั้งหมด

สมมติว่าบรรทัดใดบรรทัดหนึ่งในไฟล์มีเลขศูนย์ทั้งหมด:

$ cat file
0 0 0 1 1 0 1 1 1 0 1 1 1 1 0 0 0 1 0 0 1 1 1 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 0 0

สำหรับบรรทัดที่สอง ผลรวมทั้งสองเป็นศูนย์ซึ่งจะทำให้ข้อผิดพลาดหารด้วยศูนย์ เราสามารถหลีกเลี่ยงได้โดยการเพิ่มคำสั่ง if ซึ่งจะพิมพ์อัตราส่วนหากมีอยู่ หรือ 0/0 ไม่มี:

if (s2>0)print s1/s2; else print s1"/"s2

รหัสที่สมบูรณ์ตอนนี้คือ:

$ awk '{f=0;s1=0;s2=0;for (i=2;i<=NF;i++){s1+=$i;if ($i && !f)s2++;f=$i}; if (s2>0)print s1/s2; else print s1"/"s2}' file
2.6
0/0

มันทำงานอย่างไร

รหัสใช้ตัวแปรสามตัว f คือแฟล็กที่เป็นจริง (1) หากเราอยู่ในกลุ่มแฟล็กและเป็นเท็จ (0) มิฉะนั้น s1 คือจำนวนที่อยู่ในบรรทัด s2 คือจำนวนกลุ่มที่อยู่ในบรรทัด

  • f=0;s1=0;s2=0

    ที่จุดเริ่มต้นของแต่ละบรรทัด เราจะเริ่มต้นตัวแปร

  • for (i=2;i<=NF;i++){s1+=$i;if ($i && !f)s2++;f=$i}

    เราวนซ้ำแต่ละฟิลด์ในบรรทัดที่เริ่มต้นด้วยฟิลด์ 2 หากฟิลด์มี 1 เราจะเพิ่มตัวนับ s1 หากฟิลด์เป็น 1 และเป็นจุดเริ่มต้นของกลุ่มใหม่ เราจะเพิ่มค่า s2

  • if (s2>0)print s1/s2; else print s1"/"s2}

    หากเราพบอย่างน้อยหนึ่งรายการ เราจะพิมพ์อัตราส่วน s1/s2 มิฉะนั้น เราจะพิมพ์ 0/0

person John1024    schedule 15.03.2015
comment
แต่คุณครับ มีบรรทัดที่ข้อมูลมีบรรทัดที่มีศูนย์ทั้งหมด เช่น (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) ดังนั้นเมื่อฉันลอง ฉันได้รับข้อผิดพลาดว่า ([vijay@glycogpu process-rawData]$ ./find-sum-and-ratio.sh 947 17 55.7059 awk: (FILENAME=outPut3.dat FNR=2) fatal: department by 0 พยายาม) สิ่งนี้สามารถเอาชนะได้หรือไม่? - person Vijay; 15.03.2015
comment
@วิเจย์ โอเค คำตอบที่อัปเดตมีรหัสสำหรับจัดการสิ่งนั้น - person John1024; 15.03.2015
comment
สิ่งนี้ไม่ได้ให้ข้อมูลที่ถูกต้องหากคุณเพิ่มหมายเลขคอลัมน์ 1 พร้อมกับข้อมูลข้อมูล อ๊อฟ: Start from column #2, up to column #45001, the data is reprsented as 0 or 1 - person Jotne; 15.03.2015

person    schedule
comment
นี่ไม่ได้ให้ข้อมูลที่ถูกต้องหากคอลัมน์สุดท้ายมี 1 ลองตัวอย่างเช่น echo data 0 1 1 | awk -F1 '{gsub(/ +/,"");n=split($0,a,"[^1]+")-2;print (n?(NF-1)/n:"0")}' ผลลัพธ์ควรเป็น 2 รหัสส่งคืน 0 - person John1024; 15.03.2015
comment
@ John1024 มันจะล้มเหลวของคอลัมน์ 1 คอลัมน์ข้อมูลที่มี 1 เช่นเดียวกับในความคิดเห็น OPs จะพยายามแก้ไขครับ. - person Jotne; 15.03.2015
comment
อัปเดตด้วยข้อมูลตัวอย่างใหม่เพื่อการคำนวณที่ถูกต้อง - person Jotne; 15.03.2015