Как сохранить дублированные строки, которые повторяются ровно n раз в pandas DataFame - PullRequest
3 голосов
/ 30 апреля 2020

У меня есть DataFrame, который выглядит примерно так: ~ 10 тыс. Строк:

    peak start  peak end    motif_start   motif_end    strand   
0   948         177         3210085       3210103      -        
1   948         177         3210047       3210065      +        
2   062         419         3223269       3223287      -        
3   062         419         3223229       3223247      +        
4   062         419         3223232       3223250      +
.
.
.   

Некоторые строки повторяются от 2 до 8 раз в столбце «пиковое начало». Мне нужно вырезать новые строки DataFrame, которые повторяются ровно n раз (n между 2 и 8).

Желаемый вывод:

n=2
    peak start  peak end    motif_start   motif_end    strand   
0   948         177         3210085       3210103      -        
1   948         177         3210047       3210065      +
n=3
    peak start  peak end    motif_start   motif_end    strand
2   062         419         3223269       3223287      -        
3   062         419         3223229       3223247      +        
4   062         419         3223232       3223250      +

И так далее для каждого n.

Я пытался:

new_df = df.groupby('peak start').head(n)

, но он также возвращает первые n строк, для строк, которые повторяются более n раз.

Я новичок в Python, поэтому ищу, возможно, существующий метод, о котором я не знаю, вместо того, чтобы перебирать фрейм данных и считать.

Есть идеи?

Ответы [ 2 ]

4 голосов
/ 30 апреля 2020

Используйте GroupBy.transform с size для исполнения boolean indexing

m = df.groupby(['peak start'])['peak start'].transform('size')
#if you want to consider both
#m = df.groupby(['peak start', 'peak end'])['peak start'].transform('size') 

Теперь вы можете фильтровать ваш фрейм данных:

df.loc[m.between(2, 8)] #inclusive = True by default 

    peak start  peak end    motif_start   motif_end    strand   
0   948         177         3210085       3210103      -        
1   948         177         3210047       3210065      +        
2   062         419         3223269       3223287      -        
3   062         419         3223229       3223247      +        
4   062         419         3223232       3223250      +

df.loc[m.eq(2)]

    peak start  peak end    motif_start   motif_end    strand   
0   948         177         3210085       3210103      -        
1   948         177         3210047       3210065      +

df.loc[m.eq(3)]


    peak start  peak end    motif_start   motif_end    strand
2   062         419         3223269       3223287      -        
3   062         419         3223229       3223247      +        
4   062         419         3223232       3223250      +

Мы также можем использовать value_counts

m = df['peak start'].value_counts()
df.loc[df['peak start'].map(m).eq(2)]

или GroupBy.filter

n = 2
my_range = range(2-1, 8+1)
df.groupby('peak_start').filter(lambda group: len(group) == n)
df.groupby('peak_start').filter(lambda group: len(group) in my_range)
3 голосов
/ 30 апреля 2020

используйте .transform и count с логическим фильтром.

s = df.groupby('peak_start')['peak_start'].transform('count')

df[s == 2]
   peak_start  peak_end  motif_start  motif_end strand
0         948       177      3210085    3210103      -
1         948       177      3210047    3210065      +


print(df[s == 3])

   peak_start  peak_end  motif_start  motif_end strand
2          62       419      3223269    3223287      -
3          62       419      3223229    3223247      +
4          62       419      3223232    3223250      +
...