Создать фрейм данных pandas на основе значения подстроки поиска строки

#python-3.x #pandas #dataframe

#python-3.x #pandas #фрейм данных

Вопрос:

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

Исходный фрейм данных — нет заголовков столбцов, все данные в строках

Желаемый фрейм данных — ограничивающий строки прямоугольника столбцами с единообразным заголовком, достоверность столбца

Мой ответ структурирован следующим образом: { «status»: «successed», «CreatedDateTime»: «2020-08-28T19:21:29Z», «lastUpdatedDateTime»: «2020-08-28T19:21:31Z», «analyzeResult»: { «version»: «3.0.0», «readResults»: [{ «страница»: 1, «угол»: 0.1296, «ширина»: 1700, «высота»: 2200, «единица измерения»: «пиксель», «линии»: [{ «BoundingBox»: [ 182, 119, 383, 119, 383, 161, 182, 160 ], » текст»: «ФОРМА 101», «слова»: [{ «BoundingBox»: [ 183, 120, 305, 120, 305, 161, 182, 161 ], » текст»: «ФОРМА», «достоверность»: 0.987 }, { «BoundingBox»: [ 318, 120, 381, 120, 382, 162, 318, 161 ], » текст»: «101», «достоверность»: 0.987 } ] }, { «BoundingBox»: [ 578, 129, 1121, 129, 1121, 163, 578, 162 ], » текст»: «Содружество Массачусетс», «слова»: [{ «BoundingBox»: [ 579, 129, 634, 129, 634, 162, 579, 161 ], » текст»: «The», «confidence»: 0.988 }, { «BoundingBox»: [ 641, 129, 868, 129, 866, 164, 640, 162 ], » текст»: «Содружество», «уверенность»: 0.979 }, { «BoundingBox»: [ 874, 129, 902, 129, 900, 164, 872, 164 ], » текст»: «of», «confidence»: 0.988 }, { «BoundingBox»: [ 908, 129, 1120, 130, 1117, 163, 906, 164 ], » текст»: «Массачусетс», «достоверность»: 0.977 } ] }, { «BoundingBox»: [ 1341, 137, 1540, 138, 1540, 164, 1341, 163 ], «текст»: «ТОЛЬКО ДЛЯ ИСПОЛЬЗОВАНИЯ DIA», «слова»: [{ «BoundingBox»: [ 1342, 138, 1392, 138, 1392, 164, 1341, 163 ], » текст»: «DIA», «достоверность»: 0.983 }, { «BoundingBox»: [ 1397, 138, 1452, 139, 1452, 164, 1397, 164 ], » текст»: «ИСПОЛЬЗОВАНИЕ», «достоверность»: 0.983 }, { «BoundingBox»: [ 1457, 139, 1539, 138, 1540, 164, 1457, 164 ], » текст»: «ТОЛЬКО», «достоверность»: 0.986 } ] }, { «BoundingBox»: [ 459, 169, 1235, 168, 1235, 202, 459, 203 ], » текст»: «Отдел несчастных случаев на производстве — Отдел 101», «слова»: [{ «BoundingBox»: [ 460, 170, 634, 170, 634, 203, 460, 204 ], » текст»: «Отдел», «достоверность»: 0.981 }, { «BoundingBox»: [ 640, 170, 669, 170, 669, 203, 640, 203 ], » текст»: «of», «достоверность»: 0.983 }, { «BoundingBox»: [ 676, 170, 821, 169, 821, 203, 676, 203 ], » текст»: «Промышленный», «достоверность»: 0.981 }, { «BoundingBox»: [ 828, 169, 967, 169, 966, 203, 828, 203 ], » текст»: «Несчастные случаи», «достоверность»: 0.952 }, { «BoundingBox»: [ 973, 169, 993, 169, 993, 203, 973, 203 ], » текст»: «-«, «достоверность»: 0.983 }, { «BoundingBox»: [ 1000, 169, 1176, 169, 1176, 203, 999, 203 ], » текст»: «Отдел», «достоверность»: 0.982 }, { «BoundingBox»: [ 1183, 169, 1236, 169, 1235, 203, 1182, 203 ], » текст»: «101», «достоверность»: 0.987 } ] }, { «BoundingBox»: [ 511, 205, 1189, 205, 1189, 233, 511, 234 ], » текст»: «Конгресс-стрит, 1, номер 100, Бостон, Массачусетс 02114-2017», «слова»: [{ «BoundingBox»: [ 513, 206, 520, 206, 519, 233, 512, 233 ], » текст»: «1», «достоверность»: 0.974 }, { «BoundingBox»: [ 525, 206, 625, 206, 624, 234, 524, 233 ], » текст»: «Congress», «confidence»: 0.981 }, { «BoundingBox»: [ 630, 206, 702, 206, 701, 234, 629, 234 ], » текст»: «Улица», «уверенность»: 0.977 }, { «BoundingBox»: [ 707, 206, 763, 206, 762, 234, 706, 234 ], » текст»: «Набор», «достоверность»: 0.983 }, { «BoundingBox»: [ 769, 206, 812, 206, 811, 234, 767, 234 ], » текст»: «100», «достоверность»: 0.983 }, { «BoundingBox»: [ 818, 206, 898, 206, 897, 234, 816, 234 ], » текст»: «Бостон», «уверенность»: 0.983 }, { «BoundingBox»: [ 903, 206, 1059, 205, 1058, 234, 902, 234 ], » текст»: «Массачусетс», «достоверность»: 0.975 }, { «BoundingBox»: [ 1064, 205, 1189, 205, 1187, 233, 1063, 234 ], » текст»: «02114-2017», «достоверность»: 0.978 } ] }, { «BoundingBox»: [ 422, 236, 1279, 237, 1279, 263, 422, 263 ], » текст»: «Информация. Строка 800-323-3249 доб. 470 в массе. Внешняя масса. — 617-727-4900 доб. 470», «слова»: [{ «BoundingBox»: [423, 237, 472, 237, 472, 263, 422, 263 ], » текст»: «Информация»., «достоверность»: 0.983 }, { «BoundingBox»: [ 477, 237, 526, 237, 526, 264, 477, 264 ], » текст»: «Строка», «достоверность»: 0.986 }, { «BoundingBox»: [ 531, 237, 674, 237, 674, 264, 531, 264 ], » текст»: «800-323-3249», «достоверность»: 0.977 }, { «BoundingBox»: [ 679, 237, 718, 237, 718, 264, 679, 264 ], » текст»: «доб.», «достоверность»: 0.982 }, { «BoundingBox»: [ 724, 237, 763, 237, 763, 264, 723, 264 ], » текст»: «470», «достоверность»: 0.986 }, { «BoundingBox»: [ 768, 237, 790, 237, 790, 264, 768, 264 ], » текст»: «в», «достоверность»: 0.987 }, { «BoundingBox»: [ 795, 237, 865, 237, 865, 264, 795, 264 ], » текст»: «Масса», «достоверность»: 0.983 }, { «BoundingBox»: [ 870, 237, 953, 237, 953, 264, 870, 264 ], » текст»: «Снаружи», «достоверность»: 0.981 }, { «BoundingBox»: [ 958, 237, 1019, 237, 1020, 264, 958, 264 ], » текст»: «Масса», «достоверность»: 0.984 }, { «BoundingBox»: [ 1025, 237, 1036, 237, 1037, 264, 1025, 264 ], » текст»: «-«, «достоверность»: 0.983 }, { «BoundingBox»: [ 1042, 237, 1184, 237, 1185, 264, 1042, 264 ], » текст»: «617-727-4900», «достоверность»: 0.975 }, { «BoundingBox»: [ 1190, 237, 1229, 238, 1229, 264, 1190, 264 ], » текст»: «доб.», «достоверность»: 0.985 }, { «BoundingBox»: [ 1234, 238, 1278, 238, 1278, 264, 1234, 264 ], » текст»: «470», «достоверность»: 0.983 } ] }, { «BoundingBox»: [ 716, 264, 984, 266, 984, 293, 715, 292 ], » текст»: «http://www.mass.gov/dia «, «слова»: [{ «BoundingBox»: [ 717, 265, 985, 267, 984, 294, 716, 293 ], » текст»: «http://www.mass.gov/dia «, «достоверность»: 0.952 }] }, { «BoundingBox»: [ 398, 299, 1289, 299, 1289, 342, 398, 342 ], » текст»: «ПЕРВОЕ СООБЩЕНИЕ РАБОТОДАТЕЛЯ О ТРАВМЕ», «слова»: [{ «BoundingBox»: [ 399, 300, 693, 300, 693, 341, 399, 343 ], » текст»: «РАБОТОДАТЕЛЯ», «уверенность»: 0.98 }, { «BoundingBox»: [ 702, 300, 836, 300, 836, 341, 702, 341 ], » текст»: «ПЕРВЫЙ», «достоверность»: 0.982 }, { «BoundingBox»: [ 845, 300, 1036, 300, 1036, 341, 844, 341 ], » текст»: «ОТЧЕТ», «достоверность»: 0.985 }, { «BoundingBox»: [ 1045, 300, 1105, 300, 1104, 342, 1044, 341 ], » текст»: «OF», «confidence»: 0.988 }, { «BoundingBox»: [ 1113, 300, 1288, 299, 1287, 343, 1113, 342 ], » текст»: «ТРАВМА», «уверенность»: 0.986 } ] }, { «BoundingBox»: [ 691, 354, 1005, 355, 1005, 395, 691, 393 ], » текст»: «ИЛИ ФАТАЛЬНОСТЬ», «слова»: [{ «BoundingBox»: [ 691, 354, 760, 355, 760, 395, 692, 394 ], » текст»: «ИЛИ», «достоверность»: 0.988 }, { «BoundingBox»: [768, 355, 1005, 356, 1003, 395, 768, 395 ], » текст»: «ФАТАЛЬНОСТЬ», «уверенность»: 0.981 } ] } ] }] } }

Комментарии:

1. предоставьте исходный фрейм данных в виде текста. print(df.to_dict(orient="records")) поэтому нам не нужно проходить OCR

Ответ №1:

Без предоставления ваших данных или объяснения это в основном делает то, что вы хотите.

  1. комментарии объясняют подход
  2. над линейной клавишей предстоит проделать дополнительную работу, однако я не вижу взаимосвязи между фактическими данными и результатом, который вы опубликовали в виде изображения
 import re
import numpy as np
import pandas as pd
df = pd.DataFrame(
{0:["analyzeResult_readResults_0_lines_0_text","analyzeResult_readResults_0_lines_0_words_0_boundingBox_0","analyzeResult_readResults_0_lines_0_words_0_boundingBox_1","analyzeResult_readResults_0_lines_0_words_0_boundingBox_2","analyzeResult_readResults_0_lines_0_words_0_boundingBox_3","analyzeResult_readResults_0_lines_0_words_0_boundingBox_4","analyzeResult_readResults_0_lines_0_words_0_boundingBox_5","analyzeResult_readResults_0_lines_0_words_0_boundingBox_6","analyzeResult_readResults_0_lines_0_words_0_boundingBox_7","analyzeResult_readResults_0_lines_0_words_0_text","analyzeResult_readResults_0_lines_0_words_0_confidence","analyzeResult_readResults_0_lines_0_words_1_boundingBox_0","analyzeResult_readResults_0_lines_0_words_1_boundingBox_1","analyzeResult_readResults_0_lines_0_words_1_boundingBox_2","analyzeResult_readResults_0_lines_0_words_1_boundingBox_3","analyzeResult_readResults_0_lines_0_words_1_boundingBox_4","analyzeResult_readResults_0_lines_0_words_1_boundingBox_5","analyzeResult_readResults_0_lines_0_words_1_boundingBox_6","analyzeResult_readResults_0_lines_0_words_1_boundingBox_7","analyzeResult_readResults_0_lines_0_words_1_text","analyzeResult_readResults_0_lines_0_words_1_confidence","analyzeResult_readResults_0_lines_1_boundingBox_0","analyzeResult_readResults_0_lines_1_boundingBox_1","analyzeResult_readResults_0_lines_1_boundingBox_2","analyzeResult_readResults_0_lines_1_boundingBox_3","analyzeResult_readResults_0_lines_1_boundingBox_4","analyzeResult_readResults_0_lines_1_boundingBox_5","analyzeResult_readResults_0_lines_1_boundingBox_6","analyzeResult_readResults_0_lines_1_boundingBox_7"],

 1:["FORM 101",183,120,305,120,305,161,182,161,"FORM",0.987,318,120,381,120,382,162,318,161,101,0.987,578,129,1121,129,1121,163,578,162],
},
 index=[17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45]
)

df = (
df
    .rename(columns={0:"key",1:"val"})
    .assign(
        b=lambda x: x["key"].str.extract("(.*)_bounding"),
        c=lambda x: x["key"].str.extract("(.*)_confidence"),
        # linekey is everything before "_bounding" or "_confidence". pull the two together
        linekey=lambda x: np.where(x["b"].isna(), 
                             np.where(x["c"].isna(), x["key"], x["c"]), 
                             x["b"]),
        # column key is every thing after line key minus leading "_"
        colkey=lambda x: x.apply(lambda r: r["key"].replace(r["linekey"], "").strip("_"), axis=1)
    )
    .assign(
        # cleanup special case line keys...
        colkey=lambda x: np.where(x["colkey"]=="", "Value", x["colkey"].replace("confidence","Confidence"))
    )
    # remove working columns
    .drop(columns=["b","c","key"])
    # mixed values and strings so use "first" and unstack to get to desired layout
    .groupby(["linekey","colkey"]).agg({"val":"first"}).unstack()
)

print(df.to_string())
  

вывод

                                                         val                                                                                                                          
colkey                                           Confidence     Value boundingBox_0 boundingBox_1 boundingBox_2 boundingBox_3 boundingBox_4 boundingBox_5 boundingBox_6 boundingBox_7
linekey                                                                                                                                                                              
analyzeResult_readResults_0_lines_0_text                NaN  FORM 101           NaN           NaN           NaN           NaN           NaN           NaN           NaN           NaN
analyzeResult_readResults_0_lines_0_words_0           0.987       NaN           183           120           305           120           305           161           182           161
analyzeResult_readResults_0_lines_0_words_0_text        NaN      FORM           NaN           NaN           NaN           NaN           NaN           NaN           NaN           NaN
analyzeResult_readResults_0_lines_0_words_1           0.987       NaN           318           120           381           120           382           162           318           161
analyzeResult_readResults_0_lines_0_words_1_text        NaN       101           NaN           NaN           NaN           NaN           NaN           NaN           NaN           NaN
analyzeResult_readResults_0_lines_1                     NaN       NaN           578           129          1121           129          1121           163           578           162
  

Комментарии:

1. Большое тебе спасибо, Роб. Есть ли какой-либо способ воздержаться от присвоения имен элементам в строках и столбцах и вместо этого использовать подстроку для перемещения элементов туда? Другими словами, существует переменное количество ограничивающих рамок в зависимости от того, сколько слов содержится в ключевой фразе, но если появляется слово «привязанный блок», я хочу переместить его в столбцы. Также это может привести к ошибке из-за различий в словах. Некоторые фразы содержат 2 слова, некоторые — 20.

2. именно так это и работает… он ищет «ограничение» без каких-либо ограничений. b=lambda x: x["key"].str.extract("(.*)_bounding"), количество не ограничено…

3. Привет, я запустил его в своем коде, и он собирает только строки и столбцы, в которых вы указали значения в верхней части блока кода. Похоже, что он не повторяет весь ответ и не форматирует его одинаково.

4. странно — можете ли вы поделиться данными со мной? google drive / github или что-то в этом роде? рад посмотреть

5. Да, я могу ограбить. Спасибо, что потратили время.