Pandas. 按标签选择. 单行输出

1 投票
2 回答
3708 浏览
提问于 2025-04-18 14:25

我正在尝试从一个名为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 个回答

0

你是在尝试填充缺失值吗?为什么要重新索引这个数据框呢?

只需要

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

希望这能帮到你。如果没有,麻烦你再说明一下你想要达到的目标。

1

首先,假设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))

撰写回答