If you were to improve your input you could get close:
Example:
import ast
import pandas as pd
# string as given is not valid...
s = '''
Name1 : Name1 - {'Name1.1': ('data1', data2,data3), 'Name1.2': ('data1', 'data2','data3')}
Name2 : Name2 - {'Name2.1': ('data1', data2,data3)}
Name3 : Name3 - {'Name3.1': ('data1', data2,data3), 'Name3.2': ('data1', 'data2','data3'),'Name3.3': ('data1', 'data2','data3')}
'''
# valid as all the dataX strings are in quotes...
s = '''
Name1 : Name1 - {'Name1.1': ('data1', 'data2','data3'), 'Name1.2': ('data1', 'data2','data3')}
Name2 : Name2 - {'Name2.1': ('data1', 'data2','data3')}
Name3 : Name3 - {'Name3.1': ('data1', 'data2','data3'), 'Name3.2': ('data1', 'data2','data3'),'Name3.3': ('data1', 'data2','data3')}
'''
ds = []
for l in s.splitlines():
d = l.split('-')
if len(d) > 1:
df = pd.DataFrame(ast.literal_eval(d[1].strip()))
ds.append(df)
for df in ds:
df.reset_index(drop=True, inplace=True)
df = pd.concat(ds, axis= 1)
cols = df.columns
cols = [((col.split('.')[0], col)) for col in df.columns]
df.columns=pd.MultiIndex.from_tuples(cols)
print(df.T)
0 1 2
Name1 Name1.1 data1 data2 data3
Name1.2 data1 data2 data3
Name2 Name2.1 data1 data2 data3
Name3 Name3.1 data1 data2 data3
Name3.2 data1 data2 data3
Name3.3 data1 data2 data3
