我有一个简单的数据框,其中的列由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
答案 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
出现的次数是多少,也不是很优雅,因为list
中DataFrame
应该避免,请执行:
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]: