텍스트 파일에서 누적 누적 숫자를 어떻게 생성합니까?


9

2 백만 줄의 텍스트 파일이 있습니다. 각 줄에는 양의 정수가 있습니다. 주파수 테이블 종류를 형성하려고합니다.

입력 파일:

3
4
5
8

출력은 다음과 같아야합니다.

3
7
12
20

이 작업은 어떻게합니까?


1
텍스트에서 빈도 를 원한다고 말합니다 . 출력 샘플이 목록입니다. 이것을 명확히 해 주시겠습니까?
Wayne_Yux

실제로 당신의 출력은 주파수 테이블 아니다
don.joey

죄송 해요. 나는 누적 빈도 표를 의미했다. 질문을 수정했습니다. 감사.

그것은 시원하지는 않지만 일반적으로 스프레드 시트에 이와 같은 작업을 수행합니다.
John U

@JohnU 나는 보통하지만 내가 가지고있는 파일에는 백만 개의 숫자가 있습니다.

답변:


20

awk:

awk '{total += $0; $0 = total}1'

$0현재 줄입니다. 따라서 각 줄에 대해을 추가 total하고 줄을 new로 설정 total한 후 후행 1은 어색한 바로 가기입니다. 모든 실제 조건에 대해 현재 줄을 인쇄하고 1조건이 true로 평가됩니다.


코드를 설명해 주시겠습니까?
George Udosen

단어 print를 사용할 수 있습니까 ?
George Udosen

예, print total}대신$0 = total}1
muru

1
@ 조지 아.
muru

9
awk 스크립트를 작성하는 짧고 이해하기 쉬운 방법은 다음과 같습니다.{print(total += $0)}
Miles

9

파이썬 스크립트에서 :

#!/usr/bin/env python3
import sys

f = sys.argv[1]; out = sys.argv[2]

n = 0

with open(out, "wt") as wr:
    with open(f) as read:
        for l in read:
            n = n + int(l); wr.write(str(n)+"\n")

쓰다

  • 스크립트를 빈 파일로 복사하여 다른 이름으로 저장하십시오. add_last.py
  • 소스 파일과 대상 출력 파일을 인수로 사용하여 실행하십시오.

    python3 /path/to/add_last.py <input_file> <output_file>
    

설명

코드는 읽기 쉽지만 자세하게 설명하면 다음과 같습니다.

  • 결과 쓰기를위한 출력 파일 열기

    with open(out, "wt") as wr:
    
  • 에 읽을 있도록 열린 입력 파일

    with open(f) as read:
        for l in read:
    
  • 줄을 읽고 새 줄의 값을 총계에 추가하십시오.

    n = n + int(l)
    
  • 결과를 출력 파일에 작성하십시오.

    wr.write(str(n)+"\n")
    


3
부족이나 시간 성능에 관한 것이 아닙니다 (백만 줄은 큰 데이터가 아닙니다). 답변의 코드는 관용적 인 파이썬이 아닙니다. 내 대답 은 더 많은 파이썬 버전입니다.
jfs

8
@JFSebastian 더 관용적 인 버전이 느린 경우 왜 그것을 선호합니까? "파이썬 (pythonic)"이라는 특별한 점은 파이썬 개발자들이 가독성을위한 코드와 표준을 공유하도록 돕는 규칙 일뿐입니다. 더 관용적 인 버전이 덜 효율적 (느리게)이면 성능보다 표준화가 더 중요한 환경에서 일하지 않는 한 사용해서는 안됩니다 (끔찍한 생각처럼 들립니다).
terdon

2
@terdon 조기 최적화에 대해 할 말이 있습니다. 장기적인 유지 관리 가능성으로 인해 가독성이 중요 할 수 있습니다.
muru

4
@muru는 확실하지만 이것은 완벽하게 읽을 수 있습니다. 범죄는 "파이 토닉"이 아닌 유일한 것입니다. 우리가 거대한 프로젝트가 아닌 7 줄의 코드에 대해 이야기하고 있다는 것은 말할 것도 없습니다. 스타일 규칙의 이름에서 효율성을 희생하는 것은 잘못된 접근법처럼 보입니다.
terdon

9

재미로

$ sed 'a+p' file | dc -e0 -
3
7
12
20

이것에 의해 작동 ppending 받는 결과를 통과 한 후 각각의 입력 라인에, 그리고 계산기 곳+pdc

   +      Pops two values off the stack, adds them, and pushes the result.
          The precision of the result is determined only by the values  of
          the arguments, and is enough to be exact.

그때

   p      Prints  the  value on the top of the stack, without altering the
          stack.  A newline is printed after the value.

-e0인수 푸시 0위에 dc스택 합계를 초기화한다.


이와 같은 것이 실제로 큰 데이터 세트보다 가장 빠를 수 있습니다.
Digital Trauma

130 만 개 라인에 @DigitalTrauma, 실제로는 거의 최저 :real 0m4.234s
야곱 Vlijm

재미는
공감에

조금 설명해주세요.
AmanicA 2012

8

배쉬에서 :

#! /bin/bash

file="YOUR_FILE.txt"

TOTAL=0
while IFS= read -r line
do
    TOTAL=$(( TOTAL + line ))
    echo $TOTAL
done <"$file"

: bash는이에 매우 느리다 real 0m53.116s: 130 만 개 라인에, 거의 분
야곱 Vlijm

@JacobVlijm 대시는 비지 박스 애쉬와 zsh (sh 모드에서)의 1.5 배 정도 빠릅니다. 물론 대시도 파이썬보다 5 배 느립니다.
muru

6

한 줄에 하나씩 표준 입력에 주어진 정수의 부분 합을 인쇄하려면 :

#!/usr/bin/env python3
import sys

partial_sum = 0
for n in map(int, sys.stdin):
    partial_sum += n
    print(partial_sum)

실행 가능한 예 .

어떤 이유로 명령이 너무 느리면; C 프로그램을 사용할 수 있습니다 :

#include <stdint.h>
#include <ctype.h>
#include <stdio.h>

int main(void)
{
  uintmax_t cumsum = 0, n = 0;
  for (int c = EOF; (c = getchar()) != EOF; ) {
    if (isdigit(c))
      n = n * 10 + (c - '0');
    else if (n) { // complete number
      cumsum += n;
      printf("%ju\n", cumsum);
      n = 0;
    }
  }
  if (n)
    printf("%ju\n", cumsum + n);
  return feof(stdin) ? 0 : 1;
}

빌드하고 실행하려면 다음을 입력하십시오.

$ cc cumsum.c -o cumsum
$ ./cumsum < input > output

실행 가능한 예 .

UINTMAX_MAX입니다 18446744073709551615.

C 코드는 다음에 의해 생성 된 입력 파일에 대해 내 컴퓨터의 awk 명령보다 몇 배 빠릅니다.

#!/usr/bin/env python3
import numpy.random
print(*numpy.random.random_integers(100, size=2000000), sep='\n')


5

아마도 다음과 같은 것을 원할 것입니다 :

sort -n <filename> | uniq -c | awk 'BEGIN{print "Number\tFrequency"}{print $2"\t"$1}'

명령 설명 :

  • sort -n <filename> | uniq -c 입력을 정렬하고 빈도 표를 반환합니다.
  • | awk 'BEGIN{print "Number\tFrequency"}{print $2"\t"$1}' 출력을 더 좋은 형식으로 바꿉니다.

예 :
입력 파일 list.txt:

4
5
3
4
4
2
3
4
5

명령 :

$ sort -n list.txt | uniq -c | awk 'BEGIN{print "Number\tFrequency"}{print $2"\t"$1}'
Number  Frequency
2   1
3   2
4   4
5   2

나는이 같은 아웃 풋은 좋은 :) ...
조지 Udosen

5

이 작업은 vim에서 수행 할 수 있습니다. 파일을 열고 다음 키 입력을 입력하십시오.

qaqqayiwj@"<C-a>@aq@a:wq<cr>

참고 <C-a>실제로 CTRL-A, 그리고 <cr>이다 캐리지 리턴 , 즉 버튼을 입력합니다.

작동 방식은 다음과 같습니다. 먼저, 우리는 처음으로 부작용이 없도록 레지스터 'a'를 지우고 싶습니다. 이것은 간단 qaq합니다. 그런 다음 우리는 다음을 수행합니다.

qa                  " Start recording keystrokes into register 'a'
  yiw               " Yank this current number
     j              " Move down one line. This will break the loop on the last line
      @"            " Run the number we yanked as if it was typed, and then
        <C-a>       " increment the number under the cursor *n* times
             @a     " Call macro 'a'. While recording this will do nothing
               q    " Stop recording
                @a  " Call macro 'a', which will call itself creating a loop

이 재귀 매크로가 실행되면 :wq<cr>저장하고 종료하기 만하면 됩니다.


1
마법의 주문을 해체하고 모든 부품을 설명하는 +1 이 부분은 너무 드물다.
John U

5

펄 원 라이너 :

$ perl -lne 'print $sum+=$_' input.txt                                                                
3
7
12
20

250 만 줄의 숫자로 처리하는 데 약 6.6 초가 걸립니다.

$ time perl -lne 'print $sum+=$_' large_input.txt > output.txt                                        
    0m06.64s real     0m05.42s user     0m00.09s system

$ wc -l large_input.txt
2500000 large_input.txt

real 0m0.908s꽤 좋습니다.
Jacob Vlijm

아주 작은 파일에있는 @JacobVlijm. 250 만 줄의 파일로 작은 테스트를 추가했습니다. 6.64 초
Sergiy Kolodyazhnyy

1
고대 시스템에서 130 만 줄을 실행했습니다.
Jacob Vlijm

3

간단한 배쉬 원 라이너 :

x=0 ; while read n ; do x=$((x+n)) ; echo $x ; done < INPUT_FILE

x현재 줄 이상에서 모든 숫자의 누적 합계입니다.
n현재 줄의 숫자입니다.

우리는 모든 줄 n을 반복 INPUT_FILE하고 숫자 값을 변수에 추가하고 x각 반복 동안 그 합계를 인쇄합니다.

Bash는 여기에서 조금 느리다. 출력을 콘솔에 출력하지 않고 2 백만 개의 항목이있는 파일에 대해 약 20-30 초가 실행될 것으로 예상 할 수 있습니다 (사용하는 방법에 관계없이 더 느리다).


3

@steeldriver의 답변과 비슷하지만 bc대신 약간 덜 신비 합니다.

sed 's/.*/a+=&;a/' input | bc

bc(및 dc) 의 좋은 점 은 임의의 정밀 계산기이므로 오버플로하거나 정수보다 정밀도가 부족하지 않다는 것입니다.

sed표현식 입력 변환 :

a+=3;a
a+=4;a
a+=5;a
a+=8;a

그런 다음에 의해 평가됩니다 bc. aBC 변수는 자동으로 초기화 각 라인 단위로 0이 a, 다음 명시 적으로 인쇄합니다.


real 0m5.642s130 만 줄에 sed는 이것에 정말 느립니다.
Jacob Vlijm
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.