访问pandas dataframe列中的字典键和值

时间:2015-04-24 12:53:28

标签: python pandas

我有一个简单的数据框,其中的列由python字典填充,格式如下:

User                          CLang
111                      {u'en': 1}
112            {u'en': 1, u'es': 1}
112            {u'en': 1, u'es': 1}
113  {u'zh': 1, u'ja': 1, u'es': 2}
113  {u'zh': 1, u'ja': 1, u'es': 2}
113  {u'zh': 1, u'ja': 1, u'es': 2}
114                      {u'es': 1}
113  {u'zh': 1, u'ja': 1, u'es': 2}

CLang列包含每个用户的不同值的频率。如何访问CLang列的单个键和值?例如,我想将User和字典中最常见的值组合在一起,形式如下:

g = df.groupby(['User','CLang')

然后计算每个值的出现次数:

d = g.size().unstack().fillna(0)

结果数据框显示为:

DLang  en  es
User                 
111     1   0
112     1   1
113     0   4
114     0   1

2 个答案:

答案 0 :(得分:1)

我不完全确定我是否正确理解了您希望输出的内容,而且我认为在dict中使用pandas.DataFrame通常不是一个好主意。

将您的DataFrame重塑为更多 pandas-like 会更好,然后您就可以使用pandas方法来解决此问题。

无论如何,如果你真的想这样做,这是一种(不是很优雅)的方式:

In [1]: import pandas as pd
In [2]: l1 = [111, 112, 112, 113, 113, 113, 114, 113]
In [3]: l2 = [{'en': 1},
              {'en': 1, 'es': 1},
              {'en': 1, 'es': 1},
              {'es': 2, 'ja': 1, 'zh': 1},
              {'es': 2, 'ja': 1, 'zh': 1},
              {'es': 2, 'ja': 1, 'zh': 1},
              {'es': 1},
              {'es': 2, 'ja': 1, 'zh': 1}]

In [4]: df = pd.DataFrame({'User': l1, 'CLang': l2})

In [5]: df
Out[5]: 
   User                           CLang
0   111                      {u'en': 1}
1   112            {u'en': 1, u'es': 1}
2   112            {u'en': 1, u'es': 1}
3   113  {u'zh': 1, u'ja': 1, u'es': 2}
4   113  {u'zh': 1, u'ja': 1, u'es': 2}
5   113  {u'zh': 1, u'ja': 1, u'es': 2}
6   114                      {u'es': 1}
7   113  {u'zh': 1, u'ja': 1, u'es': 2}

In [6]: def whatever(row):
  ....:     tmp_d = {}
  ....:     for d in row.values:
  ....:         for k in d.keys():
  ....:             if k in tmp_d.keys():
  ....:                 tmp_d[k] += 1
  ....:             else:
  ....:                 tmp_d[k] = 1
  ....:     return tmp_d

In [7]: new_df = df.groupby('User')['CLang'].apply(whatever).unstack().fillna(0)

In [8]: new_df
Out[8]: 
      en  es  ja  zh
User                
111    1   0   0   0
112    2   2   0   0
113    0   4   4   4
114    0   1   0   0

如果您想知道CLang出现的次数是多少,也不是很优雅,因为listDataFrame应该避免,请执行:

In [9]: def whatever2(row):                                                  
  ....:     tmp_d = {}
  ....:     for i, v in zip(row.index, row.values):
  ....:         if v in tmp_d.keys():
  ....:             tmp_d[v].append(i)
  ....:         else:
  ....:             tmp_d[v] = [i]
  ....:     highest = max(tmp_d.keys())
  ....:     return tmp_d[highest]

In [10]: new_df['Most_Used_CLang'] = new_df.apply(whatever2, axis=1)
In [11]: new_df
Out[11]:
      en  es  ja  zh Most_Used_CLang
User                                
111    1   0   0   0            [en]
112    2   2   0   0        [en, es]
113    0   4   4   4    [es, ja, zh]
114    0   1   0   0            [es]

答案 1 :(得分:1)

我想,这是不言自明的:

> In [413]: x
Out[413]: 
                            CLang  User
0                      {u'en': 1}   111
1            {u'en': 1, u'es': 1}   112
2            {u'en': 1, u'es': 1}   112
3  {u'zh': 1, u'ja': 1, u'es': 2}   113
4  {u'zh': 1, u'ja': 1, u'es': 2}   113
5  {u'zh': 1, u'ja': 1, u'es': 2}   113
6                      {u'es': 1}   114
7  {u'zh': 1, u'ja': 1, u'es': 2}   113

In [414]: paste
temp = pd.DataFrame(index=x['User'])
for i in x.iterrows():
        clan = i[1]['CLang']
        user = i[1]['User']
        for j in clan.iteritems():
                if j[0] not in temp.columns:
                        temp[j[0]] = pd.np.NaN
                        temp[j[0]][user] = j[1]
                else:
                        temp[j[0]][user] += j[1]

print temp

## -- End pasted text --
      en  es  zh  ja
User                
111    1 NaN NaN NaN
112  NaN   2 NaN NaN
112  NaN   2 NaN NaN
113  NaN NaN   4   4
113  NaN NaN   4   4
113  NaN NaN   4   4
114  NaN NaN NaN NaN
113  NaN NaN   4   4

In [415]: temp.reset_index().groupby('User').sum()
Out[415]: 
      en  es  zh  ja
User                
111    1 NaN NaN NaN
112  NaN   4 NaN NaN
113  NaN NaN  16  16
114  NaN NaN NaN NaN

In [416]: