如何使字典键是数据帧中的一列到列中?

2024-10-04 09:31:58 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个数据框,其中一列包含包含字典的字符串化列表。我想知道如何从这些字典键生成新的列。你知道吗

我正在寻找使用pandas方法的解决方案,比如apply stack etc,而不是尽可能地使用FOR循环。你知道吗

问题是:

speakers = ['Einstein','Newton']
views = [1000,2000]
ratings0 = ("[{'id': 7, 'name': 'Funny', 'count': 100}, {'id': 1, 'name': 'Sad', "
 "'count': 110}, {'id': 9, 'name': 'Happy', 'count': 120}]")

ratings1 = ("[{'id': 7, 'name': 'Happy', 'count': 200}, {'id': 3, 'name': 'Funny', "
 "'count': 210}, {'id': 2, 'name': 'Sad', 'count': 220}]")


ratings = [ratings0, ratings1]
df = pd.DataFrame({'speaker': speakers, 'ratings': ratings,'views':views})

print(df)
speaker                                            ratings  views
0  Einstein  [{'id': 7, 'name': 'Funny', 'count': 100}, {'i...   1000
1    Newton  [{'id': 7, 'name': 'Happy', 'count': 200}, {'i...   2000

我目前的努力

# new dataframe only for ratings
dfr = df['ratings'].apply(ast.literal_eval)
dfr = dfr.apply(pd.DataFrame)
dfr = dfr.apply(lambda x: x.sort_values(by='name'))
dfr = dfr.apply(pd.DataFrame.stack)

print(dfr)

 0               1               2          
  count id   name count id   name count id   name
0   100  7  Funny   110  1    Sad   120  9  Happy
1   200  7  Happy   210  3  Funny   220  2    Sad

这提供了多索引数据帧。我试着对字典排序,但仍然没有排序,而且列name的值也不相同。另外,我不确定如何移动列name的值来替换列count,并删除其他不需要的列。你知道吗

最终通缉方案

speaker   views Funny Sad Happy
Einstein  1000 100   110 120  
Newton    2000 210   220 200

非常感谢您的帮助!!你知道吗

更新
我使用的是pands0.20,我的工作场所没有.explode()方法,不允许我更新pandas。你知道吗


Tags: nameiddf字典countnewtonviewsfunny
3条回答

对于pandas >= 0.25.0,可以使用ast.literal_eval+explode+pivot

ii = df.set_index('speaker')['ratings'].apply(ast.literal_eval).explode()

u = pd.DataFrame(ii.tolist(), index=ii.index).reset_index()

u.pivot('speaker', 'name', 'count')

name      Funny  Happy  Sad
speaker
Einstein    100    120  110
Newton      210    200  220

对于旧版本的pandas

a = df['speaker']
b = df['ratings']

ii = [
  {**{'speaker': name}, **row}
  for name, element in zip(a, b) for row in ast.literal_eval(element)
]

pd.DataFrame(ii).pivot('speaker', 'name', 'count')

因为循环并不总是坏的。你可以试一试:

dfr = pd.DataFrame(columns=['id','name','count'])

for i in range(len(df)):
    x = pd.DataFrame(df['ratings'].apply(ast.literal_eval)[i])
    x.index = [i]*len(x)
    dfr = dfr.append(x)


dfr = dfr.reset_index()   
dfr = (dfr.drop('id',axis=1)
         .pivot_table(index=['index'], columns='name',
                      values='count',aggfunc='sum')
         .rename_axis(None, axis=1).reset_index())

df_final = df.join(dfr)
df_final.drop(['index','ratings'],axis=1,inplace=True)

df_final

提供:

    speaker  views  Funny  Happy  Sad
0  Einstein   1000    100    120  110
1    Newton   2000    210    200  220

您可以使用sumindex.repeat来构造一个新的数据帧,并将其加入df[['speaker', 'views']]并将其分配给df1。接下来是set_indexunstackreset_index

df['ratings'] = df['ratings'].apply(ast.literal_eval)
df1 = (pd.DataFrame(df.ratings.sum(), index=df.index.repeat(df.ratings.str.len()))
                   .drop('id', 1).join(df[['speaker', 'views']]))
df1.set_index(['speaker', 'views', 'name'])['count'].unstack().reset_index()

Out[213]:
name   speaker  views  Funny  Happy  Sad
0     Einstein  1000   100    120    110
1     Newton    2000   210    200    220

注意name在最终输出中是列轴的标签。如果您不想看到它,只需按如下方式链接附加的rename_axis

df1.set_index(['speaker', 'views', 'name'])['count'].unstack().reset_index() \
                                                    .rename_axis([None], axis=1)

Out[214]:
    speaker  views  Funny  Happy  Sad
0  Einstein  1000   100    120    110
1  Newton    2000   210    200    220

相关问题 更多 >