【问题标题】:Print rows with condition on field data打印带有字段数据条件的行
【发布时间】:2020-11-04 12:36:28
【问题描述】:

我有数据文件

cell   input     out    type      fun            level
AI20   A1,A2      Z     comb    ((A1A2))           2
IA2    A1,A2,A3   Z     comb    ((!A1A2)A3)        3
XOR    A1,A2,B1   Z     comb    (((A1A2)B1)        3
IAD    A1,A2,A3   Z     comb    (!((A1A2)A3))      3
INV    I1         ZN    comb    (!I1)              1  
BUF  A1,A2,A3,B1  Z     comb    (!(((A1A2)A3)B1))  4

根据这些数据,我想打印level field (6th column) 给出sum 7 的行。

在这里得到level sum7我们可以选择AI2O,BUF,INV行给水平总和为2+4+1=7并打印它们Or可以选择XOR,IAD,INV给和3+3+1=7并打印出来。任何随机选择的行都有效,但 level sum 必须是 7

输出可以为

cell   input     out    type      fun            level
AI20   A1,A2      Z     comb    ((A1A2))           2
INV    I1         ZN    comb    (!I1)              1  
BUF  A1,A2,A3,B1  Z     comb    (!(((A1A2)A3)B1))  4

或者输出也可以


cell   input     out    type      fun            level
XOR    A1,A2,B1   Z     comb    (((A1A2)B1)        3
IAD    A1,A2,A3   Z     comb    (!((A1A2)A3))      3
INV    I1         ZN    comb    (!I1)              1

我用 awk 试过了

awk '{{ sum[i] += $6} for (i=1;i<8;i++) print $0}' file

但这是每行打印 7 次而不是所需的输出。

第 2 部分。请继续第 1 部分。

带有数据的文件2

cell   input  out  type   fun  level
CLK    C       Z    seq   Cq   1      
DFk    C,Cp    Q    seq   IQ   1
DFR    D,C     Qn   seq   IN   1
SKN    SE,Q    Qp   seq   Iq   1

第 2 部分的输出

cell   input     out    type      fun            level
AI20   A1,A2      Z     comb    ((A1A2))           2
INV    I1         ZN    comb    (!I1)              1  
BUF  A1,A2,A3,B1  Z     comb    (!(((A1A2)A3)B1))  4
CLK    C          Z     seq      Cq                1
XOR    A1,A2,B1   Z     comb    (((A1A2)B1)        3
IAD    A1,A2,A3   Z     comb    (!((A1A2)A3))      3
INV    I1         ZN    comb    (!I1)              1
DFk    C,Cp       Q     seq      IQ                1
IA2    A1,A2,A3   Z     comb    ((!A1A2)A3)        3
XOR    A1,A2,B1   Z     comb    (((A1A2)B1)        3
INV    I1         ZN    comb    (!I1)              1

part2 的输出是,当我们得到 file1 的 level sum 为 7 时,在其后插入 file2 的第一行。并再次检查级别总和 7 的条件,如果为真,则从 file2 插入第二行。然后再次检查级别总和为 7。如果为真,则从 file2 插入第 3 行。这样做是为了执行 3 次。

【问题讨论】:

  • 由于 for 循环,您的 awk 命令每行运行 7 次,导致每行打印 7 次
  • 那么如何检查获取总和为 7 的行的条件?
  • 你的等级栏有多长?你想要总和为 7 的所有组合吗?并且您想要任何长度的组合(例如,1-1-1-1-1-1-1 也会被选中?)
  • @IoaTzimas .. 级别列非常大,大约 600 行,级别列重复编号为 1、2、3、4、5.. 组合可以是任意长度。你的例如也可以使用。我只想要一个显示总和 7 的组合。但是是的,每次选择应该是随机的当我执行代码时。
  • 好的,你想要什么输出?所有可能的行组合?如果有 600 行,您可能会遇到很大的效率问题。例如 200 行产生超过 100 万个 3 项的组合

标签: awk sed


【解决方案1】:

这里是这个工作的 awk 解决方案:

cat rnd.awk
function rnd(max) {        # generate a randon number between 2 and max
   return int(rand()*max-1)+2
}
BEGIN {
   srand()                 # seed random generation
}
NR == 1 {                  # for header row
   print                   # print header record
   next
}
{
   rec[NR] = $0            # save each record in rec array with NR as key 
   num[NR] = $NF           # save last column in num array with NR as key
}
END {
   while(1) {              # infinite loop
      r = rnd(NR)          # generate a randomm number between 2 and NR
      if (!seen[r]++)      # populate seen array with this random number
         s += num[r]       # get aggregate sum from num array

      if (s == 7)          # if sum is 7 then break the loop
         break
      else if (s > 7) {    # if sum > 7 then restart the loop
         delete seen
         s = 0
         continue
      }
   }
   for (j in seen)         # for each val in seen print rec array
      print rec[j]
}

将其用作:

awk -f rnd.awk file
cell   input     out    type      fun            level
AI20   A1,A2      Z     comb    ((A1A2))           2
INV    I1         ZN    comb    (!I1)              1
BUF  A1,A2,A3,B1  Z     comb    (!(((A1A2)A3)B1))  4

又一次:

awk -f rnd.awk file
cell   input     out    type      fun            level
IA2    A1,A2,A3   Z     comb    ((!A1A2)A3)        3
XOR    A1,A2,B1   Z     comb    (((A1A2)B1)        3
INV    I1         ZN    comb    (!I1)              1

【讨论】:

  • 这是一个很好的答案,我正在寻找如何在这个问题上创建排列和组合,为在这里分享好的解决方案而欢呼,谢谢先生。
  • 感谢@RavinderSingh13。该算法基于在 2 和 row_count-1 之间生成的随机数生成(因为有标题行)。我们不断为s 中的随机行添加$NF,只要s==7 我们退出并打印这些记录。
  • 是的,先生,这很棒。我对此还有一些问题。我是不是应该单独问。
  • 我会在这里回答您的问题,但如果是针对不同的问题,您也可以发布新问题
  • 先生,我已经添加到上面的问题中,part2 有 file2 和给定的数据。在此,我想在我们获得级别总和为 7 后添加CLK line from file2。并对文件 1 重复此过程 3 次。所需的输出也显示在上面。在您上面的代码中,我们可以更改while loop to for loop with i &lt;= 3 condition,但是如何在if (s==7) 为真之后从file2 添加行。
【解决方案2】:

在这个问题中有两个地方效率很重要:

  1. 生成所有可能的组合;
  2. 知道组合后检索正确的行。

第一个问题在很大程度上取决于您作为“级别”拥有的可能值的数量。如果您有“数百个”不同的值,那么为您提供所需总和的可能组合的数量将非常大,因此,您需要优化算法的这一部分。

第二部分取决于文件中的行数。为了解决这个问题,我将创建一个哈希表,其中键是“级别”的值,值是字符串数组,每个字符串都是您的行之一。 获得给定组合后,您可以通过以下步骤几乎立即生成(几乎无限)组合:

  1. 检索与组合中存在的每个level 值关联的字符串数组;
  2. 从每个字符串数组中检索一个随机字符串; 3 重复该过程以获得与level 数字的给定组合相关联的尽可能多的字符串组合。

【讨论】:

    【解决方案3】:

    以下函数将返回行的随机组合,其中级别列的总和与目标相等(根据您的问题,当前为 7)。它可以与任何数据框(只要有一个数字列“级别”)和任何目标一起使用:

    import random
    
    def get_one(df, target):    
        indices=[]
        values=[]
        while sum(values)<target:
            dftemp=df[(df['level']<=target-sum(values)) & (df['level']>0)]
            ind1=random.choice([i for i in set(dftemp.index)-set(indices)])
            indices.append(ind1)
            values.append(df.loc[ind1, 'level'])
        return df.loc[indices, :]
    

    要获得结果,只需使用 df 和您的目标作为参数运行函数:

    >>>get_one(df, 7)
    
    cell   input     out    type      fun            level
    AI20   A1,A2      Z     comb    ((A1A2))           2
    INV    I1         ZN    comb    (!I1)              1  
    BUF  A1,A2,A3,B1  Z     comb    (!(((A1A2)A3)B1))  4
    

    如果要其他合计,可以更改参数,例如:

    >>>get_one(df, 10)
    >>>get_one(df, 15)
    

    【讨论】:

    • yourdf 这里是file name containing data??
    • @IoaTzimas 哦...因为这个(df['level']&lt;=target-sum(values)) 总和不能高于 7... 对吧?
    • @RiccardoPetraglia 没错! 'level' 列可能的新值不能给出大于目标的总和
    • 不,它适用于您想要的任何总数,而不仅仅是 7。我添加了一些描述,如何使用其他总数运行代码
    • 我的函数 get_one() 的输入 (df) 和输出是数据帧。要从文件创建数据框或将数据框保存到文件,您可以使用多种方法。最好的解决方案之一是使用 pd.read_csv('file1') 读取 file1 和 df.to_csv('newfile.csv') 将新数据帧写入文件的 pandas。
    猜你喜欢
    • 2016-08-03
    • 2015-02-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-03
    • 2021-11-09
    • 1970-01-01
    • 2021-10-29
    相关资源
    最近更新 更多