Поиск строки между столбцами DataFrame, которая соответствует шаблону

У Bash действительно есть функция, называемая Замена процесса , чтобы выполнить это.

$ echo <(yes)
/dev/fd/63

Здесь выражение <(yes) заменено на путь имени (псевдо-устройства) файл, подключенный к стандартным выводам асинхронного задания yes (который печатает строку y в бесконечном цикле).

Теперь попробуем прочитать:

$ cat /dev/fd/63
cat: /dev/fd/63: No such file or directory

Проблема здесь в том, что процесс yes завершился тем временем, потому что он получил SIGPIPE (у него не было читателей на stdout).

Решение представляет собой следующую конструкцию

$ exec 3< <(yes)  # Save stdout of the 'yes' job as (input) fd 3.

Это откроет файл как входной файл fd 3 перед запуском фонового задания.

Теперь вы можете читать из фонового задания, когда захотите. Для глупого примера

$ for i in 1 2 3; do read <&3 line; echo "$line"; done
y
y
y

Обратите внимание, что это имеет несколько другую семантику, чем задание фонового задания на файл с резервным копированием: фоновое задание будет заблокировано при заполнении буфера (вы освободите буфер чтение с fd). В отличие от этого, запись в файл с резервным копированием только блокируется, когда жесткий диск не отвечает.

Подстановка процесса не является функцией POSIX sh.

Вот быстрый взломать предоставить поддержку асинхронного задания (почти) без присвоения имени файла:

$ yes > backingfile &  # Start job in background writing to a new file. Do also look at `mktemp(3)` and the `sh` option `set -o noclobber`
$ exec 3< backingfile  # open the file for reading in the current shell, as fd 3
$ rm backingfile       # remove the file. It will disappear from the filesystem, but there is still a reader and a writer attached to it which both can use it.

$ for i in 1 2 3; do read <&3 line; echo "$line"; done
y
y
y

Linux также недавно добавила опцию O_TEMPFILE, что делает такие взломы возможными, если файл вообще не отображается вообще. Я не знаю, поддерживает ли bash его.

UPDATE:

@rthur, если вы хотите захватить весь вывод из fd 3, используйте

output=$(cat <&3)

Но обратите внимание, что вы не можете записывать двоичные данные в целом: это только определенная операция, если вывод представляет собой текст в смысле POSIX. Реализации, которые я знаю, просто отфильтровывают все байты NUL. Кроме того, POSIX указывает, что все конечные новые строки должны быть удалены.

(Обратите внимание также, что при записи результата будет выводиться OOM, если автор никогда не останавливается (yes никогда не останавливается). Но, естественно, эта проблема сохраняется даже для read, если разделитель строк никогда не записывается дополнительно)

0
задан Suzana 21 February 2019 в 13:45
поделиться

2 ответа

Это даст вам результат, но медленно.

import re
import pandas as pd

a = pd.DataFrame({"strings_to_search" : ["AA1 BB2 CVC GF2","AR1 KP1","PL3 4OR 91K GZ3"]})
b = pd.DataFrame({"regex_search" : ["^(?=.*AA1).*$", "^(?=.*AR1)(?=.*PL3).*$", "^(?=.*4OR)(?=.*GZ3).*$"]})

a.insert(1,'regex','')

for item in b.regex_search:
    for s in a.strings_to_search:
        if(re.match(item,s)):
            a.regex.loc[a.strings_to_search == s] = item

print(a)
0
ответ дан Yongkang Zhao 21 February 2019 в 13:45
поделиться

Вы можете объединить свой Dataframe, а затем использовать функцию apply для выполнения поиска по регулярному выражению. В этом примере я переименовал ваш re DataFrame в r, поскольку re - это имя модуля. Сначала выполните декартово произведение двух DataFrames. Затем в lambda регулярное выражение regex_search оценивается в каждой строке и выводится логическое значение, указывающее, дает ли поиск True, если выражение существует в strings_to_search или False, если выражение не существует , Наконец, отфильтруйте DataFrame по месту совпадений, сгруппируйте по strings_to_search и сгенерируйте список всех совпадающих regex_search.

import pandas as pd
import re

a["idx"] = 1
r["idx"] = 1
df = a.merge(r, on="idx").drop("idx", axis=1)

df["output"] = df.apply(lambda x: bool(re.compile(x["regex_search"]).search(x["strings_to_search"])), axis=1)

df[df["output"] == True].groupby("strings_to_search")["regex_search"].apply(list)
0
ответ дан vealkind 21 February 2019 в 13:45
поделиться
Другие вопросы по тегам:

Похожие вопросы: