Как выбрать целочисленные значения и значения с плавающей точкой в ​​каждой строке? - PullRequest
0 голосов
/ 30 марта 2020

У меня есть фрейм данных, который состоит из строк, с плавающей точкой и целых чисел в каждой строке? Мне нужно извлечь все целые числа и значения с плавающей точкой справа налево, пока не появится алфавит? Фрейм данных (df1):

df1:
    text
0   NS-100ML(GLASS) IV 1 19.25
1   India 560 into SI  10  63.26
2   INJ 2 914.20

Мне нужен вывод df1, например

df1:
    text
0   [1,   19.25]
1   [10,  63.26]
2   [2,   914.20]

Примечание. Пожалуйста, не предлагайте мне взять последние две строки, bcs мой следующий фрейм данных (df2) выглядит по-другому, как показано ниже,

df2:
    text
0   NS-100ML(GLASS) IV 1.00 4.95 63.36 96.45
1   India into 456 SI  8.0 52.30 53.46 12.03
2   INJ 2.0 63.80 34.30 56.36

I df2 выводит как

df2:
    text
0   [1.0, 4.95,  63.36, 96.45]
1   [8.0, 52.30, 53.46, 12.03]
2   [2.0, 63.80, 34.30, 56.36]

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

Ответы [ 5 ]

1 голос
/ 30 марта 2020

Вы можете комбинировать строковые методы replace и split для pandas Series. Обратите внимание, что точка (.) в квадратных скобках означает буквальную точку.

df1['text'].str.extract("( [0-9 .]+)$", expand=False).str.split()

0    [1, 19.25]
1    [10, 63.26]
2    [2, 914.20]


df2['text'].str.extract("( [0-9 .]+)$", expand=False).str.split()

0    [1.00, 4.95, 63.36, 96.45]
1    [8.0, 52.30, 53.46, 12.03]
2    [2.0, 63.80, 34.30, 56.36]

Дополнительный пример из комментариев

df = pd.DataFrame({'text':['NEOVEC INJ 385251 APR/2021 5.00 89.00 445.00']})

df['text'].str.extract("( [0-9 .]+)$", expand=False).str.split()

0    [5.00, 89.00, 445.00]
1 голос
/ 30 марта 2020

Вы можете использовать регулярное выражение:

^(\d+)\s+.*\D\s+(?=((?:\d+(?:\.\d+)?\s*)+)$)

Демо

с установленным многострочным флагом (или вставить (?m) в начале).

Для строки (например)

0   NS-100ML(GLASS) IV 1 19.25

группа захвата 1 будет содержать 0, а группа захвата 2 будет содержать 1 19.25. Заменить строку желаемой строкой, полученной из содержимого двух групп захвата, должно быть легко. Механизм регулярных выражений

Python выполняет следующие операции.

^                # match beginning of line
(\d+)            # match 1+ digits in cap grp 1
\s+              # match 1+ spaces
.*               # match 0+ chars
\D               # match a char other than a digit
\s+              # match 1+ spaces
(?=              # begin positive lookahead
  (              # begin cap grp 2
    (?:          # begin non-cap grp
      \d+        # match 1+ digits
      (?:\.\d+)  # match '.' followed by 1+ digits in non-cap grp
      ?          # optionally match non-cap grp
      \s*        # match 0+ spaces
    )            # end non-cap grp
    +            # match non-cap grp 1+ times
  )              # end cap grp 2
  $              # match end of line
)                # end positive lookahead
1 голос
/ 30 марта 2020

Попробуйте комбинацию применения с регулярным выражением,

df1['text'].apply(lambda x: [i for i in x.split() if not re.match('[A-Za-z\W]', i)])

0     [1, 19.25]
1    [10, 63.26]
2    [2, 914.20]


df2['text'].apply(lambda x: [i for i in x.split() if not re.match('[A-Za-z\W]', i)])


0    [1.00, 4.95, 63.36, 96.45]
1    [8.0, 52.30, 53.46, 12.03]
2    [2.0, 63.80, 34.30, 56.36]
0 голосов
/ 30 марта 2020

Вот метод, использующий str.split и explode

print(df2)

                                       text
0  NS-100ML(GLASS) IV 1.00 4.95 63.36 96.45
1      India into SI  8.0 52.30 53.46 12.03
2                INJ 2.0 63.80 34.30 56.36 


number_list = pd.to_numeric(df2["text"].str.split(" ").explode(), errors="coerce").dropna().groupby(
    level=0
).agg(list)

print(number_list)

0    [1.0, 4.95, 63.36, 96.45]
1    [8.0, 52.3, 53.46, 12.03]
2     [2.0, 63.8, 34.3, 56.36]
Name: text, dtype: object
0 голосов
/ 30 марта 2020

Я предполагаю, что числа разделены одним пробелом. Если бы у вас была одна строка, я бы использовал:

def extract_numbers(row):
    entries = row['text'].split(' ')
    ans = []
    while entries:
        item = entries.pop()
        try:
            num = float(item)
        except ValueError:
            # we encountered non-numerical data
            return ans
        else:
            ans = [num] + ans
   return ans

Теперь у вас есть фрейм данных.

df['numbers'] = df['text'].apply(extract_numbers)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...