Pandas. 按标签选择. 单行输出
我正在尝试从一个名为D的pandas数据框中选择每个特定用户ID对应的所有条目,并将缺失的etime值用零填充,方法如下:
user_entries = D.loc[userid]
user_entries.index = user_entries.etime
user_entries = user_entries.reindex(range(distinct_time_entries_num))
user_entries = user_entries.fillna(0)
问题是,对于某些用户ID,只有一条记录,因此使用.loc()方法时返回的是一个带有意外索引的Series对象:
(Pdb) user_entries.index = user_entries.etime
*** TypeError: Index(...) must be called with a collection of some kind, 388 was passed
(Pdb) user_entries
etime 388
requested 1
rejected 0
Name: 351, dtype: int64
(Pdb) user_entries.index
Index([u'etime', u'requested', u'rejected'], dtype='object')
这让人很难处理。我更希望得到一个只有一行的DataFrame对象。有没有办法解决这个问题?谢谢。
更新:我得为表达不清而道歉,这是我第一次在这里发帖。我再试一次。事情是这样的:有一个数据框,以用户ID为索引。每个用户ID可能对应最多N行数据框(列包括:'etime'、'requested'、'rejected'),其中'etime'基本上是关键。对于某些'userid',存在所有N个对应的条目,但对于大多数用户ID,某些'etime'的条目是缺失的。
我的意图是:为每个'userid'构建一个明确的DataFrame对象,包含所有N个条目,并按'etime'索引,缺失的条目用零填充。这就是为什么我将索引改为'etime',然后用完整的'etime'范围重新索引选定的行子集。
问题是:对于某些'userid',只有一个对应的'etime',这时使用.loc()子集时返回的不是一个按'userid'索引的只有一行的DataFrame,而是一个按数组索引的Series对象:
Index([u'etime', u'requested', u'rejected'], dtype='object')
这就是为什么更改索引会失败。每次选择数据框子集时检查维度和索引看起来都很麻烦。我还能做些什么呢?
更新2:这里是一个演示这个情况的脚本
full_etime_range = range(10)
df = DataFrame(index=[0,0,1],
columns=['etime','requested'],
data=[[0,1],[1,1],[1,1]])
for i in df.index:
tmp = df.loc[i]
tmp.index = tmp['etime']
tmp = tmp.reindex(full_etime_range,fill_value = 0)
print tmp
2 个回答
你是在尝试填充缺失值吗?为什么要重新索引这个数据框呢?
只需要
user_entries = D.loc[userid]
user_entries.fillna(0)
这样就可以解决问题了。不过如果你只是想填充etime字段的缺失值,你应该这样做:
user_entries = D.loc[userid]
temp = user_entries["etime"].fillna(0)
user_extries["etime"] = temp
希望这能帮到你。如果没有,麻烦你再说明一下你想要达到的目标。
首先,假设df
是你的数据框,我们可以安全地这样做:
In[215]: df.set_index([df.index, 'etime'], inplace=True)
In[216]: df
Out[216]:
requested
etime
0 0 1
1 1
1 1 1
DF = pd.DataFrame(index=full_etime_range, columns=[])
df0 = DF.copy()
In[225]: df0.join(df.loc[0])
Out[225]:
requested
0 1
1 1
2 NaN
3 NaN
4 NaN
5 NaN
6 NaN
7 NaN
8 NaN
9 NaN
In[230]: df1 = DF.copy()
In[231]: df1.join(df.loc[1])
Out[231]:
requested
0 NaN
1 1
2 NaN
3 NaN
4 NaN
5 NaN
6 NaN
7 NaN
8 NaN
9 NaN
这其实就是你想要的结果。不过,看看我们可以更优雅地做到这一点:
listOfDf = [DF.copy().join(df.loc[i]) for i in df.index.get_level_values(1).unique()]
我还想再进一步优化一下,但下面的做法没有成功——也许有人能解释一下为什么。
df.groupby(level=0).apply(lambda x: DF.copy().join(x))