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

Я пытаюсь прочитать электронную таблицу Excel, не отформатированную с помощью Pandas. На одном листе есть несколько таблиц, и я хочу преобразовать эти таблицы в фреймы данных. Поскольку он еще не «проиндексирован» традиционным способом, значимых индексов столбцов или строк нет. Есть ли способ найти определенное значение и получить строку, столбец, в котором оно находится? Например, скажем, я хочу получить строку, номер столбца для всех ячеек, содержащих строку «Заголовок».

Я уже пробовал такие вещи, как DataFrame.filter, но это работает, только если есть индексы строк и столбцов.

Преобразование HTML-таблицы в профессиональный документ Excel
Преобразование HTML-таблицы в профессиональный документ Excel
Это самый простой способ создания Excel из HTML-таблицы.
Импорт excel в laravel в базу данных
Импорт excel в laravel в базу данных
Здравствуйте, дорогой читатель, в этой статье я расскажу практическим и быстрым способом, как импортировать файл Excel в вашу базу данных с помощью...
5
0
15 708
7
Перейти к ответу Данный вопрос помечен как решенный

Ответы 7

Вот пример получения всех индексов строк и столбцов ячеек, содержащих слово «заголовок»:

df = pd.DataFrame({'A':['here goes the title', 'tt', 'we have title here'],
                  'B': ['ty', 'title', 'complex']})
df


+---+---------------------+---------+
|   |          A          |    B    |
+---+---------------------+---------+
| 0 | here goes the title | ty      |
| 1 | tt                  | title   |
| 2 | we have title here  | complex |
+---+---------------------+---------+


idx = df.apply(lambda x: x.str.contains('title'))

col_idx = []
for i in range(df.shape[1]):
    col_idx.append(df.iloc[:,i][idx.iloc[:,i]].index.tolist())


out = []
cnt = 0
for i in col_idx:
    for j in range(len(i)):
        out.append((i[j], cnt))
    cnt += 1
out

# [(0, 0), (2, 0), (1, 1)]   # Expected output

Вы можете просто создать маску той же формы, что и ваш df, вызвав df == 'title'. Затем вы можете объединить это с методом df.where(), который установит все поля в NA, которые отличаются от вашего ключевого слова, и, наконец, вы можете использовать dropna(), чтобы уменьшить его до всех допустимых полей. Затем вы можете использовать df.columnns и df.index, как вы привыкли.

df = pd.DataFrame({"a": [0,1,2], "b": [0, 9, 7]})
print(df.where(df == 0).dropna().index)
print(df.where(df == 0).dropna().columns)

#Int64Index([0], dtype='int64')
#Index(['a', 'b'], dtype='object')
Ответ принят как подходящий

Вы можете долго и трудно читать список:

# assume this df and that we are looking for 'abc'
df = pd.DataFrame({'col':['abc', 'def','wert','abc'], 'col2':['asdf', 'abc', 'sdfg', 'def']})

[(df[col][df[col].eq('abc')].index[i], df.columns.get_loc(col)) for col in df.columns for i in range(len(df[col][df[col].eq('abc')].index))]

вне:

[(0, 0), (3, 0), (1, 1)]

Я должен отметить, что это (значение индекса, расположение столбца)

вы также можете изменить .eq() на str.contains(), если ищете какие-либо строки, содержащие определенное значение:

[(df[col][df[col].str.contains('ab')].index[i], df.columns.get_loc(col)) for col in df.columns for i in range(len(df[col][df[col].str.contains('ab')].index))]

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

for row in df.itertuples():
    col_count = 0
    for col in row:
        if regex.match(str(col)):
            tuples.append((row_count, col_count))
            col_count+=1
        row_count+=1

return tuples

Создайте df с NaN, где your_value не найдено. Удалите все строки, в которых нет значения. Удалите все столбцы, в которых нет значения

    a = df.where(df=='your_value').dropna(how='all').dropna(axis=1)

Чтобы получить строку (и)

    a.index

Чтобы получить столбец (и)

    a.columns  

Другой подход, который в духе решения @ It_is_Chris, но может быть немного проще для чтения:

# assuming this df and that we are looking for 'abc'
df = pd.DataFrame({'col':['abc', 'def','wert','abc'], 'col2':['asdf', 'abc', 'sdfg', 'def']})
[x[1:] for x in ((v, i, j) for i, row_tup in enumerate(df.itertuples(index=False)) for j, v in enumerate(row_tup)) if x[0] == "abc"]

Вывод

[(0, 0), (1, 1), (3, 0)]

Ответ от @firefly сработает, если второй dropna получит how = 'all' тоже вот так:

a = df.where(targetMap == 'your_value').dropna(how='all').dropna(how='all',axis=1)

Другие вопросы по теме