타임스탬프를 삽입하고 CSV 파일의 빈 필드를 바꿉니다.

타임스탬프를 삽입하고 CSV 파일의 빈 필드를 바꿉니다.

다음 요소가 포함된 CSV 파일이 있습니다.

timestamp,      data1,  data2,  data3,  data4,  data5
2015-03-16 00:00:00,    3,  3,  4,  2,  5
2015-03-16 00:10:00,    4,  7,  8,  9,  3
2015-03-16 00:20:00,    1,  23, ,   5,  4
2015-03-16 00:30:00,    3,  2,  46, 7,  6
2015-03-16 00:40:00,    4,  5,  6,  8,  4
2015-03-16 00:50:00,    2,  ,   4,  ,   2
2015-03-16 01:00:00,    22, 1,  3,  4,  3
2015-03-16 01:50:00,    3,  ,   7,  8,  89
2015-03-16 02:00:00,    44, 5,  6,  7,  
2015-03-16 02:10:00,    3,  2,  1,  2,  2
2015-03-16 02:20:00,    4,  ,   ,   3,  3
2015-03-16 03:30:00,    5,  6,  7,  4,  3

NaN누락된 타임스탬프를 추가하고 다음과 같이 데이터가 존재하지 않는 데이터 필드를 채우고 싶습니다 .

timestamp,      data1,  data2,  data3,  data4,  data5
2015-03-16 00:00:00,    3,  3,  4,  2,  5
2015-03-16 00:10:00,    4,  7,  8,  9,  3
2015-03-16 00:20:00,    1,  23, NaN,    5,  4
2015-03-16 00:30:00,    3,  2,  46, 7,  6
2015-03-16 00:40:00,    4,  5,  6,  8,  4
2015-03-16 00:50:00,    2,  NaN,    4,  NaN,    2
2015-03-16 01:00:00,    22, 1,  3,  4,  3
2015-03-16 01:10:00,    NaN,    NaN,    NaN,    NaN,    NaN
2015-03-16 01:20:00,    NaN,    NaN,    NaN,    NaN,    NaN
2015-03-16 01:30:00,    NaN,    NaN,    NaN,    NaN,    NaN
2015-03-16 01:40:00,    NaN,    NaN,    NaN,    NaN,    NaN
2015-03-16 01:50:00,    3,  NaN,    7,  8,  89
2015-03-16 02:00:00,    44, 5,  6,  7,  NaN
2015-03-16 02:10:00,    3,  2,  1,  2,  2
2015-03-16 02:20:00,    4,  NaN,    NaN,    3,  3
2015-03-16 02:30:00,    NaN,    NaN,    NaN,    NaN,    NaN
2015-03-16 02:40:00,    NaN,    NaN,    NaN,    NaN,    NaN
2015-03-16 02:50:00,    NaN,    NaN,    NaN,    NaN,    NaN
2015-03-16 03:00:00,    NaN,    NaN,    NaN,    NaN,    NaN
2015-03-16 03:10:00,    NaN,    NaN,    NaN,    NaN,    NaN
2015-03-16 03:20:00,    NaN,    NaN,    NaN,    NaN,    NaN
2015-03-16 03:30:00,    5,  6,  7,  4,  3

어떻게 해야 하나요? 이 현상은 하루가 아니라 며칠 동안 지속된다는 점에 유의하세요. 단순화를 위해 하루 분량의 데이터를 사용했습니다. 저는 Cygwin을 사용하고 있습니다. 감사합니다.

답변1

타임스탬프 구문 분석을 실제로 지원하는 구현이 없고 CSV 구문 분석 이외의 구문 분석에 대한 지원이 없기 awk때문에 대신 아래 Miller를 사용하고 있습니다.awk단순한CSV(내장된 구분 기호 또는 줄바꿈 없음).

사용밀러( mlr)는 CSV를 구문 분석하고, 공백을 정리하고, 누락된 타임스탬프를 생성하고, 마지막으로 누락된 값을 문자열로 바꿉니다 NaN.

mlr --csv \
    clean-whitespace then \
    put 't1 = strptime($timestamp,"%F %T");
         NR > 1 {
             while (@t + 600 != t1) {
                 @t += 600;
                 timestamp = strftime(@t,"%F %T");
                 emit timestamp
             }
         }
         @t = t1' then \
    unsparsify then \
    put 'for (k,v in $*) { is_empty(v) { $[k] = "NaN" } }' file

clean-whitespace작업은 모든 필드에서 모든 측면 공간을 제거하고 모든 연속 내부 공간을 단일 공간으로 압축합니다.

put표현식 중 첫 번째는 누락된 타임스탬프를 생성합니다. 이는 "현재 시간"(Unix 시간 사용)을 추적하고 @t입력에서 읽은 타임스탬프에 해당할 때까지 600초(10분) 단위로 진행하여 이를 수행합니다 t1. 각 단계마다 타임스탬프가 파일과 동일한 형식으로 출력됩니다. 이를 위해 각 입력 타임스탬프가 10분 간격으로 발생한다고 가정합니다.

첫 번째 표현식으로 생성된 새 레코드에는 을 put제외한 모든 필드가 누락되어 있으므로 누락된 필드 추가를 timestamp사용합니다 .unsparsify

두 번째 put표현식은 모든 필드를 반복하고 각 빈 필드를 string 으로 설정합니다 NaN.

질문의 데이터를 고려하면 출력은 다음과 같습니다.

timestamp,data1,data2,data3,data4,data5
2015-03-16 00:00:00,3,3,4,2,5
2015-03-16 00:10:00,4,7,8,9,3
2015-03-16 00:20:00,1,23,NaN,5,4
2015-03-16 00:30:00,3,2,46,7,6
2015-03-16 00:40:00,4,5,6,8,4
2015-03-16 00:50:00,2,NaN,4,NaN,2
2015-03-16 01:00:00,22,1,3,4,3
2015-03-16 01:10:00,NaN,NaN,NaN,NaN,NaN
2015-03-16 01:20:00,NaN,NaN,NaN,NaN,NaN
2015-03-16 01:30:00,NaN,NaN,NaN,NaN,NaN
2015-03-16 01:40:00,NaN,NaN,NaN,NaN,NaN
2015-03-16 01:50:00,3,NaN,7,8,89
2015-03-16 02:00:00,44,5,6,7,NaN
2015-03-16 02:10:00,3,2,1,2,2
2015-03-16 02:20:00,4,NaN,NaN,3,3
2015-03-16 02:30:00,NaN,NaN,NaN,NaN,NaN
2015-03-16 02:40:00,NaN,NaN,NaN,NaN,NaN
2015-03-16 02:50:00,NaN,NaN,NaN,NaN,NaN
2015-03-16 03:00:00,NaN,NaN,NaN,NaN,NaN
2015-03-16 03:10:00,NaN,NaN,NaN,NaN,NaN
2015-03-16 03:20:00,NaN,NaN,NaN,NaN,NaN
2015-03-16 03:30:00,5,6,7,4,3

답변2

mktime()GNU awk를 사용하여 시간 함수( 및 strftime()) 실행 gensub()\s:

$ cat tst.awk
BEGIN { FS=OFS="," }
{ gsub(/\s*,\s*/,",") }
NR == 1 { print; next }
NR == 2 {
    dfltData = gensub(/[^,]/,"","g")
    prevSecs = mktime(gensub(/[- :]/," ","g",$1))
}
{
    currTime = $1
    currData = $0
    while ( prevTime < currTime ) {
        prevTime = strftime("%F %T",prevSecs += 600)
        if ( prevTime < currTime ) {
            $0 = dfltData
            $1 = prevTime
            prt()
        }
    }
    $0 = currData
    prt()
}

function prt() {
    $0 = gensub(/,(,|$)/,",Nan\\1","g") # this needs 2 passes
    print gensub(/,(,|$)/,",Nan\\1","g")
}

$ awk -f tst.awk file
timestamp,data1,data2,data3,data4,data5
2015-03-16 00:00:00,3,3,4,2,5
2015-03-16 00:10:00,4,7,8,9,3
2015-03-16 00:20:00,1,23,Nan,5,4
2015-03-16 00:30:00,3,2,46,7,6
2015-03-16 00:40:00,4,5,6,8,4
2015-03-16 00:50:00,2,Nan,4,Nan,2
2015-03-16 01:00:00,22,1,3,4,3
2015-03-16 01:10:00,Nan,Nan,Nan,Nan,Nan
2015-03-16 01:20:00,Nan,Nan,Nan,Nan,Nan
2015-03-16 01:30:00,Nan,Nan,Nan,Nan,Nan
2015-03-16 01:40:00,Nan,Nan,Nan,Nan,Nan
2015-03-16 01:50:00,3,Nan,7,8,89
2015-03-16 02:00:00,44,5,6,7,Nan
2015-03-16 02:10:00,3,2,1,2,2
2015-03-16 02:20:00,4,Nan,Nan,3,3
2015-03-16 02:30:00,Nan,Nan,Nan,Nan,Nan
2015-03-16 02:40:00,Nan,Nan,Nan,Nan,Nan
2015-03-16 02:50:00,Nan,Nan,Nan,Nan,Nan
2015-03-16 03:00:00,Nan,Nan,Nan,Nan,Nan
2015-03-16 03:10:00,Nan,Nan,Nan,Nan,Nan
2015-03-16 03:20:00,Nan,Nan,Nan,Nan,Nan
2015-03-16 03:30:00,5,6,7,4,3

관련 정보