61000개의 열과 173개의 행이 있는 텍스트 파일이 있습니다. 2개 열마다 데이터를 병합하고 싶습니다. 즉, 1열과 2열을 병합하고, 3열과 4열을 병합하고, 5열과 6열을 병합해야 합니다.
입력 예(탭으로 구분):
Ind Pop scaffold1 X scaffold1 X.1 scaffold3 X.2 scaffold4 X.3
a antartica 1 1 1 1 2 2 1 1
b antartica 1 1 1 1 2 1 1 2
c antartica 1 1 1 1 2 1 1 1
d antartica 1 1 1 1 2 1 1 2
e antartica 1 1 1 1 2 1 1 2
f arctic 1 1 1 1 2 1 1 1
g arctic 1 1 1 2 2 1 1 1
h arctic 1 1 1 1 2 1 1 1
I arctic 1 1 1 1 2 1 1 1
j arctic 1 1 1 1 2 1 1 1
원하는 출력(탭으로 구분):
Ind-Pop scaffold1-X scaffold2-X.1 scaffold3-X.2 scaffold4-X.3
a-antartica 1-1 1-1 2-2 1-1
b-antartica 1-1 1-1 2-1 1-2
c-antartica 1-1 1-1 2-1 1-1
d-antartica 1-1 1-1 2-1 1-2
e-antartica 1-1 1-1 2-1 1-2
f-arctic 1-1 1-1 2-1 1-1
g-arctic 1-1 1-2 2-1 1-1
h-arctic 1-1 1-1 2-1 1-1
I-arctic 1-1 1-1 2-1 1-1
j-arctic 1-1 1-1 2-1 1-1
R에서 tidyr 패키지의 unity 함수를 사용하여 이 작업을 수행해 보았습니다. 다음 명령을 사용하여 한 번에 두 개의 열을 병합할 수 있습니다.
unite(df, newcol, c(scaffold1, X), remove=TRUE)
여러 열을 사용하여 이 작업을 수행하는 방법을 잘 모르겠습니다.
R, Perl 또는 Linux 명령줄 방법을 사용하면 매우 감사하겠습니다!
답변1
sed -E 's/([^\t]+)\t([^\t]+)/\1-\2/g'
설명하다
sed -E 's/foo/bar/g'
: 확장 정규식을sed
사용하여 실행하고 각 줄을 , 여러 번 바꿉니다.-E
foo
bar
/g
([^\t]+)\t([^\t]+)
[^\t]
: 탭이 아닌 문자 길이의 하나 이상의 문자를 일치시키고+
이를 그룹으로 캡처합니다([^\t]+)
. 그 뒤에는 탭 문자가 오고 다른 캡처 그룹의 탭이 아닌 문자가 옵니다.\1-\2
-
: 첫 번째 캡처링 그룹으로 바꾼 다음 두 번째 캡처링 그룹으로 바꿉니다 . 기본적으로 탭을-
.
이것이 작동하는 이유
sed
"탐욕적"입니다. 즉, 가능한 한 많은 문자를 얻으려고 합니다. 따라서 두 캡처 그룹 모두 가능한 한 오랫동안 유지하려고 노력합니다. 예를 들어, 모두 가져옵니다 a antartica
( 로 대체 a-antartica
). 다음에 검색을 실행하면 지나가고 antartica
해당 단어 다음 탭에서 다시 검색이 시작됩니다. 그래서 다음 게임은 이고 1 1
, 로 대체될 것입니다 1-1
. 그러면 각 열 쌍에 대해 패턴이 반복됩니다. 탐욕 +
은 중요합니다. 생략하면 각 탭만 수정되는 모드입니다.
답변2
다음은 "file.tsv" 입력에 사용할 수 있는 몇 가지 방법입니다.
$ perl -pe 's/\t/("-",$&)[$|--]/ge' file.tsv
여기서는 모든 홀수 탭을 대시로 바꿉니다.
$ sed -e '
y/\t/\n/
:a;s/\n/-/;s//\t/;ta
' file.tsv
이 sed 코드는 먼저 모든 탭을 줄 바꿈으로 변경한 다음 점차적으로 홀수를 대시로, 짝수를 탭으로 변경합니다.
$ perl -lpe 's/\t(.*?(?:\t|$))/-$1/g' file.tsv
$ perl -F'\t' -lane '
push @A, join "-", splice @F,0,2 while @F;
print join "\t", splice @A;
' file.tsv
$ perl -F'\t' -nae '($,,$")=("\t", "-");
print map { "@F[2*$_,2*$_+1]" } 0..$#F/2;
' file.tsv