Q:

How to merge columns with dynamic number of columns

I am working on an AI project that involves handling a lot of data frames in Python. I am trying to append values to df, however, I want to make the number of columns of df dynamic depending on the number of columns of the data frame a. rowMerge is a function that takes two variables (a and b). a is a data frame that we provide and b is a data frame that we expect the function to return. This function enables me to merge rows when a has five columns. 
def rowMerger(a,b):
try:
    b = pd.DataFrame(data=None, columns =[f'Column{i}' for i in range(0, len(a.columns))])
    rule1 = lambda x: x not in ['']
    u = a.loc[a['Column0'].apply(rule1) & a['Column1'].apply(rule1) & a['Column2'].apply(rule1)].index
    findMergerindexs = list(u)
    findMergerindexs.sort()
    a = pd.DataFrame(a)
    if (len(findMergerindexs) > 0):
       for m in range(len(findMergerindexs)):
           if not (m == (len(findMergerindexs)-1)): 
               startLoop = findMergerindexs[m]
               endLoop = findMergerindexs[m+1]
           else:
               startLoop = findMergerindexs[m]
               endLoop = len(a)
           Column0 = ''
           Column1 = ''
           Column2 = ''
           Column3 = ''
           Column4 = ''
           for n in range(startLoop,endLoop):
               Column0 = Column0 + str(a.iloc[n,0])
               Column1 = Column1 + str(a.iloc[n,1])
               Column2 = Column2 + str(a.iloc[n,2])
               Column3 = Column3 + str(a.iloc[n,3])
               Column4 = Column4 + str(a.iloc[n,4])
           b = b.append({'Column0': Column0.strip(), 'Column1': Column1.strip(), 'Column2': Column2.strip(), 'Column3': Column3.strip(), 'Column4': Column4.strip()}, ignore_index=True)
    else:
        print("File is not having a row for merging instances - Please check the file manually for instance - ")
except: 
    print("Error - While merging the rows")
return b

I above function is a function I made to merge rows so that I can get rid of the space in between the lines. For example, I have a data frame as shown below. 
    df=[['7','4','5','7','8'],["","","",'7','4'],['9','4','7','8','4'],["","","",'7','5'],['4','8','5','4','6']]
df=pd.DataFrame(df)
df.columns=[f'Column{i}' for i in range(0, len(df.columns))]

Column0 Column1 Column2 Column3 Column4
7       4       5       7       8 
                        7       4
9       4       7       8       4
                        7       5
4       8       5       4       6

And the function rowMerger removes the space in between the lines and gives me a data frame that looks like below. 
rowMerger(df,0)
    Column1 Column2 Column3 Column4 Column5
    7       4       5       77       84
    9       4       7       87       45
    4       8       5       4         6

However, this function is not dynamic. That is, the number of columns of variable b is determined manually. Instead, I want to make the number of columns generated inside the function to be dynamic, based on the number of columns of the variable a. For instance, if the number of columns of a is three, I want to create three columns (Column0,Column0,Column0) and append values to those columns and return a data frame with three columns. 
I have tried everything I could but this is something out of my capability. I am still learning python and I would really appreciate it if anyone can help me with this.

A:

Here is a function that could help; it works for the example u provided, but u'll have to tweak it to accommodate many other scenarios : The idea is to find the rows that have empty strings, get the columns for those rows, combine them and pass them somehow back to the original dataframe. I put comments in the code; hopefully, they should explain well enuf. Lemme know how it goes. Someone else could possibly have a better one, so just play with it and c.
 def process_data(df):

    #convert to string
    #easier to merge rows
    df = df.astype(str)

    #find rows where there are empty strings
    empty_rows_index = df.loc[df.eq('').any(axis=1)].index

    #find columns where there are no empty strings
    non_empty_cols = df.loc[:,df.ne('').all()].columns.tolist()

    #this gets us the index above the rows with empty strings
    empty_rows_pair = [[ind-1,ind] for ind in empty_rows_index]

    #pair index with columns
    rows_cols = [[entry,non_empty_cols] for entry in empty_rows_pair]

    #this combines the columns where empty strings are in the next row
    #with the non empty string row in the previous column
    lump = [df.loc[x,y].sum().astype('int') for x,y in rows_cols]

    #combine and flip, so that the column names are the headers
    merger = pd.concat(lump,axis=1).T

    #to ensure complete reintegration back to the dataframe
    #set the merger index to the previous row index
    merger.index = [i for i,j in empty_rows_pair]

    #drop the empty string rows
    df = df.drop(empty_rows_index)

    #set the rows in df to match with
    #the rows and columns in merger
    #and assign merger to that section
    df.loc[merger.index,merger.columns] = merger

    df = df.astype(int).reset_index(drop=True)
    return df

    process_data(df)

    Column0 Column1 Column2 Column3 Column4
0       7      4       5      77     84
1       9      4       7      87     45
2       4      8       5      4      6

