WebOrCode
WebOrCode

Reputation: 7284

Pandas make dataFrame from list of multiple nametuples, but with individual members

I know the title is not best if somebody has better idea of how to describe my problem, feel free to change it.

Code:

from collections import namedtuple

Point = namedtuple('Point', 'x y')
x1 = Point(1, 2)
x2 = Point(3, 4)
x3 = Point(6, 5)

PointWithData = namedtuple('PointWithData', 'Point1 Point2 Point3 weight description')

data = [
    PointWithData(x1, x2, x3, 3.4, 'test1'),
    PointWithData(x2, x3, x1, 2.1, 'test2'),
    PointWithData(x3, x1, x2, 1.8, 'test3'),
]

df = pd.DataFrame(
    data,
)

df

Output:

Point1  Point2  Point3  weight  description
0   (1, 2)  (3, 4)  (6, 5)  3.4 test1
1   (3, 4)  (6, 5)  (1, 2)  2.1 test2
2   (6, 5)  (1, 2)  (3, 4)  1.8 test3

Each Point is as a tuple, but I want it as individual members.
Like this

    p1_x  p1_y  p2_x  p2_y  p3_x  p3_y  weight  description
0   1     2     3     4     6     5        3.4  test1
1   3     4     6     5     1     2        2.1  test2
2   6     5     1     2     3     4        1.8  test3

Upvotes: 0

Views: 42

Answers (2)

BENY
BENY

Reputation: 323226

You can try unnesting with axis=0

unnesting(df,['Point1','Point2','Point3'],axis=0)
Out[25]: 
   Point1x  Point1y  Point2x  Point2y  Point3x  Point3y  weight description
0        1        2        3        4        6        5     3.4       test1
1        3        4        6        5        1        2     2.1       test2
2        6        5        1        2        3        4     1.8       test3

def unnesting(df, explode, axis):
    if axis==1:
        idx = df.index.repeat(df[explode[0]].str.len())
        df1 = pd.concat([
            pd.DataFrame({x: np.concatenate(df[x].values)}) for x in explode], axis=1)
        df1.index = idx

        return df1.join(df.drop(explode, 1), how='left')
    else :
        df1 = pd.concat([
                         pd.DataFrame(df[x].tolist(), index=df.index).add_prefix(x) for x in explode], axis=1)
        return df1.join(df.drop(explode, 1), how='left')

Upvotes: 1

Celius Stingher
Celius Stingher

Reputation: 18367

You can try with this:

df['p1_x'] = df['Point1'].str.get(0)
df['p1_y'] = df['Point1'].str.get(1)
df['p2_x'] = df['Point2'].str.get(0)
df['p2_y'] = df['Point2'].str.get(1)
df['p3_x'] = df['Point3'].str.get(0)
df['p3_y'] = df['Point3'].str.get(1)
df2 = df.drop(columns=['Point1','Point2','Point3'])
print(df2)

Output:

   weight description  p1_x  p1_y  p2_x  p2_y  p3_x  p3_y
0     3.4       test1     1     2     3     4     6     5
1     2.1       test2     3     4     6     5     1     2
2     1.8       test3     6     5     1     2     3     4

Upvotes: 1

Related Questions