Как читать файлы Excel, если в некоторых ячейках несколько строк

#python #excel #pandas

Вопрос:

Мне нужно прочитать несколько больших файлов Excel, чтобы попытаться очистить данные.

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

Это что-то вроде этого:

 Index Col1 Col2   Col3
1     row1 row1   row1
2          row1.1
3          row1.2
4     row2 row2   row3
 

Когда я использую Pandas.read_excel(имя файла) или Pandas.Выделите файл, затем sheet.parse(имя листа), он, конечно, читается в индексах 2 и 3 в основном пустыми строками.

Как бы я мог объединить индексы 2 и 3 в 1 на основе того, что охватывает Col1?

Чтобы прояснить мой вопрос: как я мог читать в файле excel и объединять строки на основе того, какие строки охватывает первый столбец? Возможно ли это вообще?

Спасибо

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

1. Как ты мог догадаться? На самом деле, это злоупотребление Excel. В Excel есть возможность переносить длинные строки в одну ячейку, которые будут экспортироваться в виде длинной записи в одной ячейке. Как бы то ни было, если Col1 бы они были расширены таким образом, как вы могли бы сказать, что это не дополнительные строки?

2. Я не создавал файлы, но да, это моя проблема. Похоже, это может занять много часов ручной работы…..

Ответ №1:

Я не знаю, встроена ли эта функциональность в Pandas, так как, честно говоря, Excel не предназначен для такого использования, но люди все равно склонны злоупотреблять этим. Чувак, я ненавижу Excel….. но это тема для другой темы.

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

Это мое предложение, основанное на моем понимании данных и того, о чем вы спрашиваете. Возможно, его потребуется изменить в зависимости от особенностей ваших файлов.

 last_valid = None
check_cols = []  # if only need to check a subset of cols for validity, do it here

for i, s in df.iterrows():  # This is slow, but probably necessary in this case
    """ If all the rows are valid, we want to keep it as a reference in case
    the following rows are not """
    if all(s[check_cols].notna()):
        lvi, last_valid = i, s  
        # need to store index and series so we can go back and replace it
        continue
    else:  # here is the critical part
        extra_vals = s[s.notna()]  # find cells in row that have actual values
        for col in extra_vals.index:
            """ I'm creating a list and appending here since I don't know
            your values or how they need to be handled exactly"""
            last_valid[col] = list(last_valid[col]).append(extra_vals[col])
        # replace that row in the dataframe
        df.iloc[lvi, :] = last_valid

# drop extra rows:
df = df.dropna(axis=0, subset=check_cols)
 

Надеюсь, это сработает для тебя!

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

1. Когда я пытаюсь это сделать, я получаю объект «float», который не может быть повторен. Я попытался переключить все столбцы с плавающей точкой на str, но все равно понял. Это происходит по адресу last_valid[col] = список(last_valid[col]).добавить(дополнительные значения[col])

2. Ах, извините за это! Не был уверен в точном форматировании, но надеюсь, что вы смогли заставить его работать.

Ответ №2:

@LiamFiddler ответ правильный, но нуждался в некоторой корректировке, чтобы работать в моей ситуации, так как я объединяю числа в одной строке и буду выводить в csv в виде строк. Я публикую свой на случай, если это поможет кому-то, кто придет сюда

 last_valid = None

        check_cols = ['Col1']  # if only need to check a subset of cols for validity, do it here
       

        df = df.astype(str) #convert all columns to strings as I have to combine numbers in the same cell

        df = df.replace('nan','') #get rid of the nan created back to a blank string

        for i, s in df.iterrows():  # This is slow, but probably necessary in this case
           

            """ If all the rows are valid, we want to keep it as a reference in case

            the following rows are not """

            if all(s[check_cols] != ''):

                lvi, last_valid = i, s

                # need to store index and series so we can go back and replace it

                continue

            else:  # here is the critical part

                extra_vals = s[s != '']  # find cells in row that have actual values

                for col in extra_vals.index:

                    """ I'm creating a list and appending here since I don't know

                    your values or how they need to be handled exactly"""

                    last_valid[col] = last_valid[col]   ","   extra_vals[col] #separate by whatever you wish, list was causing issues

                # replace that row in the dataframe

                df.iloc[lvi, :] = last_valid

 

        # drop extra rows:

        df = df[df['Col1'] != ''].reset_index(drop=True)