2017-10-17 76 views
4

我已經看到herehere關於如何返回每第n行;但我的問題是不同的。文件中的單獨列提供了關於返回哪個第n個元素的細節;這取決於組別而不同。以下是Nth列提供要返回的行的數據集示例。也就是說,對於Ida每隔3行和對Idb每隔4行。這些數據非常大,有幾個Id組。從組中的文件中取出每第n行,並在列中給出n爲

Id TagNo Nth 
a A-A-3 3 
a A-A-1 3 
a A-A-5 3 
a A-A-2 3 
a AX-45 3 
a AX-33 3 
b B-B-5 4 
b B-B-4 4 
b B-B-3 4 
b BX-B2 4 

所需的輸出:

Id TagNo Nth 
a A-A-3 3 
a A-A-2 3 
b B-B-5 4 

謝謝您的幫助。

編輯:請注意,我想開始從first和每第n項採摘;即ab的第三個。對於組a它將是1st,4th, 7th ...對於組b將爲1st,5th, 9th行。原始輸出有錯誤,編輯完成。我真誠的道歉。

+0

爲什麼'AX-45'呢? – Sotos

+0

必須是一個拼寫錯誤,這個想法是返回每個'第三'爲'a'和每個'4th'爲'b'。將做一個編輯。 – deepseefan

+0

首先? (因爲你也有'A-A-3') – Sotos

回答

2

基地R溶液:

do.call(rbind, lapply(split(df, df$Id), function(x) x[seq(from = 1, to = nrow(x), by = unique(x$Nth)), ])) 

    Id TagNo Nth 
a.1 a A-A-3 3 
a.4 a A-A-2 3 
b b B-B-5 4 
+0

這真的是一個很好的解決方案,你可以嘗試一些data.table –

+0

可悲的是,我不熟悉data.table。但這裏有一些人(akrun,Sotos和其他人),他們應該能夠將其轉換爲data.table。 – LAP

+0

我找到了'data.table'解決方案:) –

2

對於awk解決方案,

$ cat awk-sc 
{ 
    if(id==$1){ 
    nth--; 
    if(nth==0){print; nth=$3} 
    } else { 
    id=$1;nth=$3;print 
    } 
} 

$ awk -f awk-sc file 
Id TagNo Nth 
a A-A-3 3 
a A-A-2 3 
b B-B-5 4 
6

awk應該工作:

awk '!a[$1]++{print; if(NR>1) n=NR+$3} NR==n{print; n=NR+$3}' file 

Id TagNo Nth 
a A-A-3 3 
a A-A-2 3 
b B-B-5 4 
1

Python的解決方案。

from __future__ import print_function 

with open('file.csv') as f: 
    print(*next(f).split()) # header 

    lastid = None 
    lineno = 0 
    for line in f: 
     id_, tagno, nth = line.split() 

     if lastid != id_: 
      lineno = 0 

     if lineno % int(nth) == 0: 
      print(id_, tagno, nth) 

     lastid = id_ 
     lineno += 1 
+0

謝謝,但它給了我'ValueError:沒有足夠的值解開(預期3,得到1)'錯誤。將首先檢查其他解決方案並回溯追蹤錯誤。 – deepseefan

+0

@deepseefan哦,所以文件真的不是*逗號分隔*。編輯。 – pacholik

+0

有兩個版本;對於分隔的逗號,它給了我'print(* next(reader))'行上的語法錯誤。 – deepseefan

1

這裏是一個base R溶液。
一,數據。我假設你用dat <- read.csv("file.csv")來閱讀它。

dat <- 
structure(list(Id = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 
2L, 2L), .Label = c("a", "b"), class = "factor"), TagNo = structure(c(3L, 
1L, 4L, 2L, 6L, 5L, 9L, 8L, 7L, 10L), .Label = c("A-A-1", "A-A-2", 
"A-A-3", "A-A-5", "AX-33", "AX-45", "B-B-3", "B-B-4", "B-B-5", 
"BX-B2"), class = "factor"), Nth = c(3L, 3L, 3L, 3L, 3L, 3L, 
4L, 4L, 4L, 4L)), .Names = c("Id", "TagNo", "Nth"), class = "data.frame", row.names = c(NA, 
-10L)) 

現在R代碼。

dat2 <- do.call(rbind, lapply(split(dat, dat$Nth), function(x) 
      x[c(1 + (1:(nrow(x) %/% x[1, "Nth"]) - 1)*x[1, "Nth"]), ])) 
row.names(dat2) <- NULL 
dat2 
# Id TagNo Nth 
#1 a A-A-3 3 
#2 a A-A-2 3 
#3 b B-B-5 4 
1

AWK單行

$ awk 'a!=$1{a=$1; n=$3; k=-1} FNR>1 && ++k%n!=0{next} 1' f1 
Id TagNo Nth 
a A-A-3 3 
a A-A-2 3 
b B-B-5 4 

a!=$1{a=$1; n=$3; k=-1}a是跟蹤第一字段/列的變量。如果a未初始化或第一列與前一列不同,則這將滿足,並且它將設置a,nk=-1

FNR>1 && ++k%n!=0{next}:增量k與第一/標題行 每行後,如果有剩餘n不給零,這意味着它不是第n個記錄,不打印。否則它是nth並打印出來。

以下的版本,以幫助您更好地瞭解:

$ awk 'FNR==1{print; next;} a!=$1{a=$1; n=$3; k=0; print; next} ++k%n==0{print}' f1 
Id TagNo Nth 
a A-A-3 3 
a A-A-2 3 
b B-B-5 4 

FNR==1{print; next;}:簡單的打印頭,什麼也不做

a!=$1{a=$1; n=$3; k=0; print; next}a是跟蹤的第一個字段/列的變量。如果a未初始化或第一列與前一列不同,則設置a,nk=0

++k%n==0{print}:繼續增加k與每個新記錄,如果其餘與n給零,這意味着它是第n條記錄。

0

Python的解決方案:

with open('YOURFILENAME', 'r') as f: 
    i = 1 
    print('Id TagNo Nth') 
    for line in f.readlines(): 
     if not i: 
      print(line, end='') 
      i = int(line.split()[-1]) 
     i -= 1 

您可以更改打印()寫(),或任何你想要的其他功能。 由於標題已修復,因此未將其包含在我的代碼中。

更新:單獨打印標題。

+0

謝謝;但你的解決方案不完整;並且它有一個錯誤:ValueError:int()的基數爲10的無效文字:'Id,TagNo,Nth'。這意味着討論[這裏](https://stackoverflow.com/questions/30903967/invalid-literal-for-int-with-base-10-what-does-this-actually-mean)。換句話說,'int'不知道如何轉換通過'line.split()[ - 1]' – deepseefan

+0

@deepseefan傳遞的參數。但我認爲問題在於你沒有跳過第一行,因爲標題中的最後一個元素是「Nth」而不是數字。 Cuz頭是固定的,我沒有在我的代碼中處理。 –

2

使用data.table

df <- data.table(read.table(text = "Id TagNo Nth 
a A-A-3 3 
a A-A-1 3 
a A-A-5 3 
a A-A-2 3 
a AX-45 3 
a AX-33 3 
b B-B-5 4 
b B-B-4 4 
b B-B-3 4 
b BX-B2 4", header = T)) 

df <- df[, id := seq_len(.N), by = Id] 
df[id %% Nth == 1 , 1:3, by = Id] 

    Id TagNo Nth 
1: a A-A-3 3 
2: a A-A-2 3 
3: b B-B-5 4 
相關問題