使用同一 Dataframe 中另一列的 int 作为索引获取列中的列表值
Posted
技术标签:
【中文标题】使用同一 Dataframe 中另一列的 int 作为索引获取列中的列表值【英文标题】:Get a list value in a column using as index an int from another column in the same Dataframe 【发布时间】:2020-12-20 13:35:41 【问题描述】:我有一个包含两列的 pandas 数据框:
df.selection
(...)
1454 5
1458 6
1473 4
1474 4
1487 4
1491 3
1500 6
Name: selection, Length: 117, dtype: int64
和
df.value_lsts
(...)
1454 [8.4, 16.0, 7.4, 3.96, 17.5, 2.6]
1458 [8.85, 3.25, 5.3, 4.95, 8.14, 11.0]
1473 [9.8, 5.28, 11.67, 15.15, 4.47, 3.06]
1474 [5.5, 2.19, 7.7, 11.98, 28.0, 8.54]
1487 [26.6, 9.74, 7.71, 6.46, 2.28, 7.58]
1491 [6.4, 3.1, 19.92, 4.2, 6.37, 11.05]
1500 [3.0, 22.91, 8.61, 13.58, 6.37, 3.69]
Name: value_lsts, Length: 117, dtype: object
这是一列列表。
我需要创建另一列,其值将由以下给出:
value_lsts[df.selection - 1]
例如对于第 1500 行,我们有
df.value_lsts
1500 [3.0, 22.91, 8.61, 13.58, 6.37, 3.69]
df.selection
1500 6
所以返回值将是 3.69
我已经尝试了所有方法,但无法提出解决方案。 通过 df.selection 列访问正确索引的 pythonic 方式是什么?
非常感谢。 皮耶罗
【问题讨论】:
我添加了性能更好的解决方案,这可能很有用。如果您仍有任何问题 - 请随时提问。如果否 - 如果您能接受任何令您满意的答案,我将不胜感激。 【参考方案1】:注意, putting mutable objects inside a DataFrame can be an antipattern
如果您确定要达到的目标并确信需要一列列表 - 您可以这样解决问题:
使用apply
方法:
df["new_column"] = df.apply(lambda raw: raw.value_lsts[raw.selection -1], axis = 1)
使用列表推导:
df["new_column"] = [x[y-1] for x, y in zip(df['value_lsts'], df['selection'])]
使用矢量化函数:
def get_by_index(value_lsts,selection): # you may use lambda here as well
return value_lsts[selection-1]
df["new_column"] = np.vectorize(get_by_index) (df['value_lsts'], df['selection'])
在我看来,选择哪个选项是可读性和性能之间的权衡。
让我们比较算法性能
创建更大的数据框
df_1 = df.sample(100000, replace=True).reset_index(drop=True)
时间
# 1. apply
%timeit df_1["new_column"] = df_1.apply(lambda raw: raw.value_lsts[raw.selection-1], axis = 1)
2.77 s ± 94.7 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
# 2. list comprehension:
%timeit df_1["new_column"] = [x[y-1] for x, y in zip(df_1['value_lsts'], df_1['selection'])]
33.9 ms ± 1.29 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
# 3. vectorized function:
%timeit df_1["new_column"] = np.vectorize(get_by_index) (df_1['value_lsts'], df_1['selection'])
12 ms ± 302 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
# 4. solution proposed by @anky using lookup
%%timeit
u = pd.DataFrame(df_1['value_lsts'].tolist(),index=df_1.index) #helper dataframe
df_1['selected_value'] = u.lookup(u.index,df_1['selection']-1)
51.9 ms ± 865 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
如果您不确定是否真的需要一列列表 - 您可以阅读proper way for splitting column of lists to multiple columns。
【讨论】:
【参考方案2】:您也可以在将一系列列表转换为数据框后在此处使用df.lookup
(请注意,python 索引从 0 开始,因此应根据您的逻辑使用selection-1
) p>
u = pd.DataFrame(df['value_list'].tolist(),index=df.index) #helper dataframe
df['selected_value'] = u.lookup(u.index,df['selection']-1)
print(df)
selection value_list selected_value
1454 5 [8.4, 16.0, 7.4, 3.96, 17.5, 2.6] 17.50
1458 6 [8.85, 3.25, 5.3, 4.95, 8.14, 11.0] 11.00
1473 4 [9.8, 5.28, 11.67, 15.15, 4.47, 3.06] 15.15
1474 4 [5.5, 2.19, 7.7, 11.98, 28.0, 8.54] 11.98
1487 4 [26.6, 9.74, 7.71, 6.46, 2.28, 7.58] 6.46
1491 3 [6.4, 3.1, 19.92, 4.2, 6.37, 11.05] 19.92
1500 6 [3.0, 22.91, 8.61, 13.58, 6.37, 3.69] 3.69
【讨论】:
以上是关于使用同一 Dataframe 中另一列的 int 作为索引获取列中的列表值的主要内容,如果未能解决你的问题,请参考以下文章