"inverted" 列表列表中的熊猫系列

Panda series from an "inverted" list of lists

有一个列表列表 idx_of_vals = [[ 3, 7, 10, 12, 9], [8, 0, 5, 1], [ 6, 4, 11, 2]](例如,13 个从 0 到 12 的随机排列的整数)。

所需的输出是一系列 s:

>>> s
0     1
1     1
2     2
3     0
4     2
5     1
6     2
7     0
8     1
9     0
10    0
11    2
12    0
Name: my_name, dtype: int64

s 中索引来自 idx_of_vals 的第 0 个元素 ([ 3, 7, 10, 12, 9]) 的元素的值为 0(即它的 indexidx_of_vals),idx_of_vals 的第一个元素的索引值为 1,依此类推。

当前解决方案:

s = pd.Series(np.nan, index=np.arange(13), name='my_name')
for val, idx in dict(enumerate(idx_of_vals)).items():
    s.loc[idx] = val
s = s.astype(int)

问题:是否有更有效和 pythonic 的方法来达到预期的结果避免 for 循环?

你可以试试听写理解

s = pd.Series(np.nan, index=np.arange(13), name='my_name')
s.update({val:idx for idx, vals in enumerate(idx_of_vals) for val in vals})
print(s)

0     1.0
1     1.0
2     2.0
3     0.0
4     2.0
5     1.0
6     2.0
7     0.0
8     1.0
9     0.0
10    0.0
11    2.0
12    0.0
Name: my_name, dtype: float64

摆动 pandas 个数据帧:

(pd.DataFrame(idx_of_vals)
   .stack()
   .droplevel(level=1)
   .sort_values()
   .index)

输出:

Int64Index([1, 1, 2, 0, 2, 1, 2, 0, 1, 0, 0, 2, 0], dtype='int64')

我会创建一个系列,explode 并交换索引和值。

idx_of_vals = [[ 3, 7, 10, 12, 9], [8, 0, 5, 1], [ 6, 4, 11, 2]]

s = pd.Series(idx_of_vals).explode()
s = pd.Series(s.index, index=s).sort_index()

输出:

0     1
1     1
2     2
3     0
4     2
5     1
6     2
7     0
8     1
9     0
10    0
11    2
12    0
dtype: int64

作为 one-liner (python ≥3.8):

pd.Series((s:=pd.Series(idx_of_vals).explode()).index, index=s).sort_index()

for循环不一定不好。您当前的解决方案比当前接受的答案更快。

使它更高效和 pythonic 的一件事不是预先分配系列然后填充它,而是重组数据然后才用它创建系列。为此,您可以使用字典理解。

idx_of_vals = [[ 3, 7, 10, 12, 9], [8, 0, 5, 1], [ 6, 4, 11, 2]]
data = {val: idx for idx, lst in enumerate(idx_of_vals) for val in lst}
s = pd.Series(data, name='my_name').sort_index()

输出:

>>> s

0     1
1     1
2     2
3     0
4     2
5     1
6     2
7     0
8     1
9     0
10    0
11    2
12    0
Name: my_name, dtype: int64