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


Вот пример получения всех индексов строк и столбцов ячеек, содержащих слово «заголовок»:
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)