Если n-й символ строки в кадре данных является определенным символом, удалите эту строку - PullRequest
1 голос
/ 08 июля 2020

У меня есть фрейм данных:

df1 = {'seq': ["(((...))).(.)", "...((.))", "..(.)..(.)"],

       'a':  [1,3,5],
        'b': [9,4,7],
        'val': [0.01, 0.02, 0.03],
        }

df1 = pd.DataFrame (df1, columns = ['seq','a','b','val'])

И я хочу указать, что если n-й символ 'seq' - это "." затем удалите эту строку, где n указано в столбце 'a'.

Ответы [ 2 ]

2 голосов
/ 08 июля 2020

Вы можете использовать apply и логическую индексацию:

df1 = df1[df1.apply(lambda r: r['seq'][r['a']-1]!='.', axis=1)]

Вывод:

             seq  a  b   val
0  (((...))).(.)  1  9  0.01
2     ..(.)..(.)  5  7  0.03
0 голосов
/ 08 июля 2020

вы можете использовать str.split с '', чтобы разделить каждый символ в новом столбце, а затем использовать индексацию, чтобы получить правильный символ в позиции, зависящей от столбца a. наконец, проверьте, где! = of '.'.

print (df1[df1['seq'].str.split('', expand=True)
                     .to_numpy()[np.arange(len(df1)), df1['a']] #no need of -1 here
           !='.'])
             seq  a  b   val
0  (((...))).(.)  1  9  0.01
2     ..(.)..(.)  5  7  0.03

для небольшого фрейма данных из 3 строк, apply если быстрее, но если размер увеличивается, этот метод становится интересным. Хотя, если строки в seq длиннее, они могут повлиять на синхронизацию.

%timeit df1[df1.apply(lambda r: r['seq'][r['a']-1]!='.', axis=1)]
# 1.15 ms ± 23.2 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
%timeit df1[df1['seq'].str.split('', expand=True).to_numpy()[np.arange(len(df1)), df1['a']]!='.']
#1.7 ms ± 95 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

#with 300 rows
df2 = pd.concat([df1]*100)
%timeit df2[df2.apply(lambda r: r['seq'][r['a']-1]!='.', axis=1)]
# 7.45 ms ± 137 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit df2[df2['seq'].str.split('', expand=True).to_numpy()[np.arange(len(df2)), df2['a']]!='.']
#2.58 ms ± 52.6 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

#with 3000 rows
df3 = pd.concat([df1]*1000)
%timeit df3[df3.apply(lambda r: r['seq'][r['a']-1]!='.', axis=1)]
#67.9 ms ± 3.6 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
%timeit df3[df3['seq'].str.split('', expand=True).to_numpy()[np.arange(len(df3)), df3['a']]!='.']
#11.4 ms ± 432 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
...