In pandas, how to collect data in all rows and make new data into a single row?

Viewed 450

I have the following data frame called data_frame:

      a         b       c
0   [1, 2]   [3, 4]   [5, 6]
1   [7, 8]   [9, 10]  [11, 12]
2   [13, 14] [15, 16] [17, 18]

What I want to do is element-wise mean of list in all rows. For instance, the result data should be:

                   a                                    b                                      c
0 [(1 + 7 + 13) / 3, (2 + 8 + 14) / 3] [(3 + 9 + 15) / 3, (4 + 10 + 16) / 3] [(5 + 11 + 17) / 3, (6 + 12 + 18) / 3]

If each element in pandas was a single value, this could be done by data_frame.mean().

However, how can it be done if each element in pandas is the list shown above?

3 Answers

Try with stack() then get mean of level 1 and aggregate back as list/join (anything you prefer):

s = df.stack()
pd.DataFrame(s.tolist(),index=s.index).mean(level=1).agg(list,1).to_frame().T

        a        b         c
0  [7, 8]  [9, 10]  [11, 12]

Convert for each column values to 2d arrays, then use mean and last convert Series to one row DataFrame:

df = df.apply(lambda x: np.array(x.tolist()).mean(axis=0).tolist()).to_frame().T
print (df)
            a            b             c
0  [7.0, 8.0]  [9.0, 10.0]  [11.0, 12.0]

Another solution, very similar principe:

df = pd.DataFrame([[np.array(df[x].tolist()).mean(axis=0).tolist() for x in df.columns]], 
                   columns=df.columns)

Summary of the code below :
Transpose dataframe and convert to numpy array
zip the entries in each sublist/array ... this pairs the numbers together... so for a, we'll have (1,7,13), (2,8,14); same thing for b and c
for each zipped entry, find the mean
create a dictionary where the outcome is paired with the columns
create the dataframe

data = {"a":[[1,2],[7,8],[13,14]], "b":[[3,4],[9,10],[15,16]], "c":[[5,6],[11,12],[17,18]]}

df = pd.DataFrame(data)

outcome = [[np.mean(entry) for entry in (zip(*ent))]
           for ent in df.T.to_numpy()]

pd.DataFrame({key:[value] for key, value in zip(df.columns, outcome)})

            a              b         c
    0   [7.0, 8.0]  [9.0, 10.0] [11.0, 12.0]
Related