【问题标题】:awk - calculate percentages if condition is metawk - 如果满足条件,则计算百分比
【发布时间】:2021-11-09 06:10:52
【问题描述】:

我从awk开始,不知道如果满足某个条件,如何计算百分比。

这是我正在使用的文件:

user,gender,age,native_lang,other_lang
0,M,19,finnish,english swedish german 
1,M,30,urdu,english 
2,F,26,finnish,english swedish german
3,M,20,finnish,english french swedish 
4,F,20,finnish,english swedish 
5,F,29,finnish,english 
6,F,23,swedish,finnish english 
7,F,19,swedish,finnish english french 
8,F,25,finnish,english swedish german russian french estonian

我想根据条件计算百分比:

  • native_lang = '芬兰语'
  • other_lang = '瑞典语'

我写的脚本如下:

awk -F ',' {$4~/finnish/ && $5~/swedish/}END{for (i in a)}

给定这些行的预期输出应该是44.44%

我找不到将“+1”添加到计算总数的变量的方法。

怎么可能?

谢谢

【问题讨论】:

  • 确保包括名称是其他语言的子字符串的语言,因为这是一个测试用例,许多脚本(如您问题中的脚本)可能会失败,例如RomaniRomanianRussianPrussian)。某些语言也是多个单词(例如 West FrisianOld Prussian),因此如果您不允许在数据中使用这些单词,请同时显示这些单词在您的日期或状态中的表示方式。
  • 什么是a?您从未向数组中添加任何内容。
  • 为什么找不到给变量加 1 的方法?只需使用variable++
  • 我预计 55.55% -- 记录 0、2、3、4、8 符合条件。
  • 我建议阅读 awk 信息页面以更好地了解该语言的语法:stackoverflow.com/tags/awk/info

标签: awk


【解决方案1】:

使用++ 增加一个变量以获取匹配数。最后除以NR-1,即输入行数(不包括表头)。

执行块的条件不在{}内,而是在前面。

脚本参数需要用引号引起来。

awk -F ',' '$4~/finnish/ && $5~/swedish/ {count++} 
            END {printf("%.2f%%\n", 100*count/(NR-1))}' filename.csv

【讨论】:

  • 如果你把语言放在边界内,那么像romaniromanian这样的重叠语言就不会失败。在任何 awk 中,您都可以使用 $4 ~ /(^| )finnish( |$)/(" "$4" ") ~ / finnish /,同样只需 5 美元。
【解决方案2】:

假设:

  • 目标是计算与给定native/other 语言对匹配的输入行的百分比
  • 输入分隔符是逗号
  • native 匹配在第 4 个输入字段
  • other 匹配在第 5 个输入字段中的一个单词上(多个单词用空格分隔)
  • 比较应该不区分大小写
  • 样本输入中有五个匹配 finnish/swedish 的结果,因此结果应该是 55.56%(而不是 OP 建议的 44.44%
  • 无需担心由多个单词组成的语言(回复:EdMorton 的评论)
  • 逗号分隔符旁边没有“额外”空格(否则我们需要修剪逗号分隔字段的前导/尾随空格)

一个awk想法:

native='finnish'
other='swedish'

awk -v native="${native}" -v other="${other}" -F"," '

BEGIN  { native = tolower(native)                 # convert everything to lower case
         other  = tolower(other)                  # to simulate case-insensitive matching
       }

FNR==1 { next }                                   # skip header; just in case "native" or "other" have a match in this line

tolower($4) == native {                           # case-insensitive match on field #4?

         n=split(tolower($5),a,"[[:space:]]")     # case-insensitive split of field #5 into components; should address EdMorton comment about substring matching multiple languages

         for (i=1;i<=n;i++)                       # loop through array looking for matches
             if (other == a[i]) {                 # and if found ...
                count++                           # increment our counter and ...
                next                              # skip to next input line; do not want to double count if there is a dupe in field #5
             }
       }

END    { if (NR >= 2)                             # as long as we have at least one data line ...
            printf "%.2f%\n", 100*count/(NR-1)    # print the % of input lines that match the "native/other" pair
       }
' users.dat

这会生成:

55.56%

【讨论】:

    猜你喜欢
    • 2021-12-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多