如果 pandas 系列的值是一个列表,如何获取每个元素的子列表?
Posted
技术标签:
【中文标题】如果 pandas 系列的值是一个列表,如何获取每个元素的子列表?【英文标题】:If the value of pandas series is a list, how to get a subList of each element? 【发布时间】:2017-12-01 06:37:48 【问题描述】:使用两个熊猫系列:series1和series2,我愿意制作series3。 series1 的每个值都是一个列表,series2 的每个值都是 series1 的对应索引。
>>> print(series1)
0 [481, 12, 11, 220, 24, 24, 645, 153, 15, 13, 6...
1 [64, 80, 79, 147, 14, 20, 56, 288, 12, 208, 26...
4 [5, 6, 152, 31, 295, 127, 711, 5, 271, 291, 11...
5 [363, 121, 727, 249, 483, 122, 241, 494, 555]
7 [112, 20, 41, 9, 104, 131, 26, 298, 65, 214, 1...
9 [129, 797, 19, 151, 448, 47, 19, 106, 299, 144...
11 [72, 35, 25, 200, 122, 5, 75, 30, 208, 24, 14,...
18 [137, 339, 71, 14, 19, 54, 61, 15, 73, 104, 43...
>>> print(series2)
0 0
1 3
4 1
5 6
7 4
9 5
11 7
18 2
我的期望:
>>> print(series3)
0 [481, 12, 11, 220, 24, 24, 645, 153, 15, 13, 6...
1 [147, 14, 20, 56, 288, 12, 208, 26...
4 [6, 152, 31, 295, 127, 711, 5, 271, 291, 11...
5 [241, 494, 555]
7 [104, 131, 26, 298, 65, 214, 1...
9 [47, 19, 106, 299, 144...
11 [30, 208, 24, 14,...
18 [71, 14, 19, 54, 61, 15, 73, 104, 43...
我的解决方案 1:
从 series1 和 series2 的长度相等的事实来看,我可以创建一个 for 循环来迭代 series1 并计算类似series1.ix[i][series2.ix[i]]
并制作一个新系列(series3)来保存结果。
我的解决方案 2:
使用df = pd_concat([series1, series2])
生成一个dataFrame df,并创建一个新列(使用apply 函数进行逐行操作 - 例如,df['series3'] = df.apply(lambda x: subList(x), axis=1)。
但是,我认为上述两种解决方案并不是实现我想要的清晰方法。如果您提出更简洁的解决方案,我将不胜感激!
【问题讨论】:
您还希望有哪些其他类型的解决方案?本质上,您将不得不遍历您的行。pandas
在设计时并未考虑将 list
s 作为值,因此不会有任何内置函数来适应矢量化列表切片之类的功能。我能想到的“最简洁”的解决方案是pd.concat([S1, S2], axis=1).apply(lambda x: x[0][x[1]:], axis=1)
(假设“列”将是简单的整数标签),但这并不比您提到的简单 for 循环更有效。
确实,看看使用简单的 Python 列表是多么容易:L1, L2 = S1.tolist(), S2.tolist()
然后简单地使用 list(map(lambda x,y : x[y:], L1, L2))
,它可能与 pandas
操作一样有效(更真实)。跨度>
1.我不想制作一个复制的 dataFrame 来执行该计算。我希望有人知道比这更好的答案。 2. 在我的情况下,将 Series 转换为 List 有点危险。如果忽略索引,可能会导致计算错误。
如果你想提高内存效率,你将不得不编写一个 for 循环。同样,pandas
和底层的numpy
并不意味着真正与list
s 一起用作值。
那么,哪种数据结构更适合处理多个列表?由于我在做特征工程(数据挖掘),所以我一直在使用 pandas dataFrame 来保存特征。
【参考方案1】:
如果您希望避免创建中间pd.DataFrame
,而只是想要一个新的pd.Series
,您可以在map
对象上使用pd.Series
构造函数。所以给定:
In [6]: S1
Out[6]:
0 [481, 12, 11, 220, 24, 24, 645, 153, 15, 13, 6]
1 [64, 80, 79, 147, 14, 20, 56, 288, 12, 208, 26]
2 [5, 6, 152, 31, 295, 127, 711, 5, 271, 291, 11]
3 [363, 121, 727, 249, 483, 122, 241, 494, 555]
4 [112, 20, 41, 9, 104, 131, 26, 298, 65, 214, 1]
5 [129, 797, 19, 151, 448, 47, 19, 106, 299, 144]
6 [72, 35, 25, 200, 122, 5, 75, 30, 208, 24, 14]
7 [137, 339, 71, 14, 19, 54, 61, 15, 73, 104, 43]
dtype: object
In [7]: S2
Out[7]:
0 0
1 3
2 1
3 6
4 4
5 5
6 7
7 2
dtype: int64
你可以这样做:
In [8]: pd.Series(map(lambda x,y : x[y:], S1, S2), index=S1.index)
Out[8]:
0 [481, 12, 11, 220, 24, 24, 645, 153, 15, 13, 6]
1 [147, 14, 20, 56, 288, 12, 208, 26]
2 [6, 152, 31, 295, 127, 711, 5, 271, 291, 11]
3 [241, 494, 555]
4 [104, 131, 26, 298, 65, 214, 1]
5 [47, 19, 106, 299, 144]
6 [30, 208, 24, 14]
7 [71, 14, 19, 54, 61, 15, 73, 104, 43]
dtype: object
如果你想修改S1
而不创建中间容器,你可以使用for循环:
In [10]: for i, x in enumerate(map(lambda x,y : x[y:], S1, S2)):
...: S1.iloc[i] = x
...:
In [11]: S1
Out[11]:
0 [481, 12, 11, 220, 24, 24, 645, 153, 15, 13, 6]
1 [147, 14, 20, 56, 288, 12, 208, 26]
2 [6, 152, 31, 295, 127, 711, 5, 271, 291, 11]
3 [241, 494, 555]
4 [104, 131, 26, 298, 65, 214, 1]
5 [47, 19, 106, 299, 144]
6 [30, 208, 24, 14]
7 [71, 14, 19, 54, 61, 15, 73, 104, 43]
dtype: object
【讨论】:
【参考方案2】:你基本上可以连接指定轴(0=行,1列)的系列,最好是相同的长度
series3=pd.concat([series2, series1], axis=1).reset_index()
【讨论】:
以上是关于如果 pandas 系列的值是一个列表,如何获取每个元素的子列表?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Pandas DataFrame 中一次获取多列的值计数?
如何检查变量是 python 列表、numpy 数组还是 pandas 系列
Python Pandas 使用 dataframe.stack().value_counts() - 如何获取计数对象的值?