Python 熊猫把字典分解成几行

Python 熊猫把字典分解成几行,python,pandas,dataframe,Python,Pandas,Dataframe,我有一个数据帧: Name Sub_Marks 0 Tom {'Maths': 30, 'English': 40, 'Science': 35} 1 Harry {'Maths': 35, 'English': 30, 'Science': 25} 2 Nick {'Maths': 32, 'English': 23, 'Science': 20} 我需要把字典分解成多行。例如 Name

我有一个数据帧:

    Name                                    Sub_Marks
0    Tom  {'Maths': 30, 'English': 40, 'Science': 35}
1  Harry  {'Maths': 35, 'English': 30, 'Science': 25}
2   Nick  {'Maths': 32, 'English': 23, 'Science': 20}
我需要把字典分解成多行。例如

    Name  Subject  Marks
0    Tom    Maths     30
1    Tom  English     40
2    Tom  Science     35
3  Harry    Maths     35
4  Harry  English     30
5  Harry  Science     25
6   Nick    Maths     32
7   Nick  English     23
8   Nick  Science     20
我知道我们可以在数据框中分解列表。使用字典有什么方法吗?

您可以使用将字典“分解”为列,然后使用将列转换为
主题
标记
列,如下所示:

(df.drop(columns='Sub_Marks')
   .join(df.apply(lambda x: pd.Series(x['Sub_Marks']), axis=1))
   .melt(id_vars='Name', value_vars=['Maths', 'English', 'Science'], var_name='Subject', value_name='Marks')
   .sort_values('Name')
).reset_index(drop=True)
您还可以使用
pd.DataFrame()
to_list()
来“分解”字典:

(df.join(pd.DataFrame(df.pop('Sub_Marks').to_list()))
   .melt(id_vars='Name', value_vars=['Maths', 'English', 'Science'], var_name='Subject', value_name='Marks')
   .sort_values('Name')
).reset_index(drop=True)
输出:

    Name  Subject  Marks
0  Harry    Maths     35
1  Harry  English     30
2  Harry  Science     25
3   Nick    Maths     32
4   Nick  English     23
5   Nick  Science     20
6    Tom    Maths     30
7    Tom  English     40
8    Tom  Science     35

我们可以通过迭代列表中dataframe的值来创建一个包含
名称
标记
主题
的元组列表,然后我们可以从这个元组列表中创建一个新的dataframe

out = pd.DataFrame([(n, k, v) for (n, d) in df.values for k, v in d.items()])
out.columns = ['Name', 'Subject', 'Marks']
备选
pandas
方法

m = pd.DataFrame([*df['Sub_Marks']], df.index).stack()\
      .rename_axis([None,'Subject']).reset_index(1, name='Marks')

out = df[['Name']].join(m)


您可以仅从
字典中提取值,然后将其展开为多列,如下所示:

data = {'Name' : ['Tom', "Harry", "Nick"], "Sub_Marks" : [{'Maths': 30, 'English': 40, 'Science': 35},{'Maths': 35, 'English': 42, 'Science': 31},{'Maths': 20, 'English': 14, 'Science': 65}]}
df = pd.DataFrame(data)

df[['Maths','English', 'Science']] = df['Sub_Marks'].apply(pd.Series)
df.drop(columns=['Sub_Marks'], inplace=True)
df = df.set_index('Name').stack().reset_index()
df.columns = ['Name', 'Subject', 'Marks']

通过
explode
-

df['Marks'] = df['Sub_Marks'].apply(lambda x: x.values())
df = df.apply(pd.Series.explode).rename(columns = {'Sub_Marks': 'Subject'})
您可能需要首先使用
ast.literal\u eval
(如果上述方法不起作用)-


哇!我喜欢你的解决方案。那个拆包很聪明。你可以解释一下
*df['Sub_Marks']
部分发生了什么吗?
*
用于将列
Sub_Marks
解包为
列表
,因此,除了使用
[*df['Sub_Marks']
之外,你还可以使用
列表(df['Sub_Marks']))
无需使用
apply
+
dict.values
,从字典列表创建一个新的数据帧会自动处理该问题;)@ShubhamSharma哦。我不确定它是否有,因为它在专栏中仍然向我显示了一个dict。但是,
apply(pd.Series)
也可以工作。
pd.DataFrame(list(df['Sub_Marks'))
将字典列表扩展到一个数据框架中,其中该框架中的列名对应字典列表中的所有唯一键,一般来说,你应该避免使用
apply
+
pd.Series
,因为这是一个计算成本更高的操作:)啊,我知道了。我想我之前误解了。另外,我不知道
apply
+
pd.Series
在计算上很昂贵。谢谢你,先生:)
df['Marks'] = df['Sub_Marks'].apply(lambda x: x.values())
df = df.apply(pd.Series.explode).rename(columns = {'Sub_Marks': 'Subject'})
import ast
df['Sub_Marks'] = df['Sub_Marks'].apply(ast.literal_eval)