【问题标题】:Case/if-else statement to create new column in new csv在新 csv 中创建新列的 case/if-else 语句
【发布时间】:2017-01-16 00:23:13
【问题描述】:

我正在尝试对 CSV 文件(例如 myfile.csv)执行 case/if-else 语句来分析列,然后在新 csv 中创建新列(例如 myfile_new.csv)。

源数据(myfile.csv)如下所示:

unique_id,variable1,variable2
1,,C
2,1,
3,,A
4,,B
5,1,

我正在尝试做两个转换:

  • 对于第二个字段,如果输入文件的字段中有数据,则为1,否则为0。
  • 第三个字段被展平为三个字段。如果输入文件的第三个字段有A,则第三个输出字段有1,否则0BC 以及输出文件中的第四个/第五个字段也是如此。

我希望结果 (myfile_new.csv) 看起来像这样:

unique_id,variable1,variable2_A,variable2_B,variable2_C
1,0,0,0,1
2,1,0,0,0
3,0,1,0,0
4,0,0,1,0
5,1,0,0,0

我正在尝试在SQL 中做同样的事情

select unique_id, 
case when len(variable1)>0 then 1 else 0 as variable1, 
case when variable2 = 'A' then 1 else 0 end as variable2_A, 
case when variable2 = 'B' then 1 else 0 end as variable2_B, 
case when variable2 = 'C' then 1 else 0 end as variable2_C, ... 

我对任何内容都持开放态度,但 CSV 文件大小为 500GB - 1TB,因此它需要使用该大小的文件。

【问题讨论】:

  • 我不明白输出中的第 4 列和第 5 列来自哪里以及您所说的“虚拟变量”是什么意思。
  • 虚拟变量意味着将分类变量展平为数值变量。鉴于第一行的变量 2 有一个“C” --> variable2_A 为 0,variable2_B 为 0,variable2_C = 1。

标签: bash csv


【解决方案1】:

这是一个可以做到的 awk 解决方案:

awk 'BEGIN {
    FS = ","
    OFS = ","
}

NR == 1 {
    $3 = "variable2_A"
    $4 = "variable2_B"
    $5 = "variable2_C"
    print
    next
}

{
    $2 = ($2 == "") ? 0 : 1
    $3 = ($3 == "A" ? 1 : 0) "," ($3 == "B" ? 1 : 0) "," ($3 == "C" ? 1 : 0)
    print
}' myfile.csv > myfile_new.csv

BEGIN 块中,我们将输入和输出文件分隔符设置为逗号。

NR == 1 块为输出文件创建标头并跳过第三个块。

第三个块检查第二个字段是否为空,并在其中存储01$3 语句将使用三元运算符?: 的结果连接三次,逗号分隔。

输出是

unique_id,variable1,variable2_A,variable2_B,variable2_C
1,0,0,0,1
2,1,0,0,0
3,0,1,0,0
4,0,0,1,0
5,1,0,0,0

【讨论】:

    【解决方案2】:

    使用 while 循环的快速而肮脏的解决方案。

    #!/bin/bash
    #Variables:
    line=""
    result=""
    linearray[0]=0
    
    while read line; do
        unset linearray #Clean the variables from the previous loop
        unset result
        IFS=',' read -r -a linearray <<< "$line" #Splits the line into an array, using the comma as the field seperator
        result="${linearray[0]}""," #column 1, at index 0, is the same in both files.
        if [ -z "${linearray[1]}" ]; then #If column 2, at index 1, is empty, then...
            result="$result""0""," #Pad empty strings with zero
        else #Otherwise...
            result="$result""${linearray[1]}""," #Copy the non-zero column 2 from the old line
        fi
        #The following read index 2, for column 3, and add on the appropriate text. Only one can ever be true.
        if [ "${linearray[2]}" == "A" ]; then result="$result""1,0,0"; fi
        if [ "${linearray[2]}" == "B" ]; then result="$result""0,1,0"; fi
        if [ "${linearray[2]}" == "C" ]; then result="$result""0,0,1"; fi
        if [ "${linearray[2]}" == "" ]; then result="$result""0,0,0"; fi
        echo $result >> myfile_new.csv #append the resulting line to the new file
    done <myfile.csv
    

    【讨论】:

      猜你喜欢
      • 2019-06-22
      • 1970-01-01
      • 2020-10-29
      • 1970-01-01
      • 1970-01-01
      • 2013-10-05
      • 2020-03-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多