从 itertools 产品创建数据框
Posted
技术标签:
【中文标题】从 itertools 产品创建数据框【英文标题】:Create dataframe from itertools product 【发布时间】:2018-08-06 17:04:14 【问题描述】:我有两个列表:
a = [1,2,3]
b = [4,5,6]
我想创建一个数据框,其中 (a,b) 的每个组合都会生成一个数据框 X,然后我选择 X 的最大值strong>,生成的输出行/列包含 a 和 b 中的元素。
df=[]
for i, j in itertools.product(a, b):
X = do_something(i,j) ## this is a dataframe
x_value = X.max()
df.append(i,j,x_value)
df=pd.DataFrame(df, columns=['a', 'b', 'x_value'])
输出数据框的列应为 a,行应为 b,值应为 x_value。
1 2 3
4
5
6
【问题讨论】:
是的,没错——更新了func
是否采用标量 i
和 j
?所以它必须在创建数据框之前或之后迭代地应用?
不,函数非常复杂,但每次迭代 (i, j) 的最终结果是一个包含许多列的数据帧。然后我从列中选择一个值
有两个问题,1) 为a
和b
的笛卡尔积生成x_value
,以及2) 用a
和b
列排列Dataframe 中的值和行。您的代码 1) 很好,但创建了一个不同的数据框,一个有 3 列和 9 行。但数据都在那里。
【参考方案1】:
IIUC
df=pd.DataFrame(columns=a,index=b)
df.apply(lambda x : x.index+x.name)
Out[189]:
1 2 3
4 5 6 7
5 6 7 8
6 7 8 9
【讨论】:
【参考方案2】:IIUC,您想知道如何从 (i, j, x)
值列表转到 DataFrame,其中 i
对应于列,j
对应于索引,x
对应于值:
例如,如果您有:
a = [1,2,3]
b = [4,5,6]
func = lambda i, j: i+j
result = [(i, j, func(i,j)) for i, j in itertools.product(a, b)]
print(result)
#[(1, 4, 5),
# (1, 5, 6),
# (1, 6, 7),
# (2, 4, 6),
# (2, 5, 7),
# (2, 6, 8),
# (3, 4, 7),
# (3, 5, 8),
# (3, 6, 9)]
将其转换为 DataFrame 的一种方法是使用 collections.defaultdict
:
from collections import defaultdict
d = defaultdict(list)
for i, j, x in result:
d[i].append(x)
df = pd.DataFrame(d, index=b)
print(df)
# 1 2 3
#4 5 6 7
#5 6 7 8
#6 7 8 9
【讨论】:
我正在简化 func(x),如果 x 比简单的加法更复杂怎么办? 它必须是 itertools,因为每个 (i,j) 都会生成一个数据帧 (temp),我会在 temp 中选择一个特定的值 每个 (i, j) 创建一个数据框 X,我挑出最大值 @user44840 我已根据您的最新更新修改了我的答案 最适合创建 2d df【参考方案3】:您可以避免使用itertools.product
,同时通过使用 numpy 和广播实现相同的功能:
a = [1,2,3]
b = [4,5,6]
arr = np.array(a).reshape(-1, 1) + np.array(b).reshape(1, -1)
df = pd.DataFrame(arr, columns=a, index=b)
【讨论】:
【参考方案4】:In [134]: a=[1,2,3]
In [135]: b=[4,5,6]
您的“指数”和值列表:
In [140]: alist = []
In [142]: for i,j in itertools.product(a,b):
...: v = i*2 + j*.5
...: alist.append([i,j,v])
...:
In [143]: alist
Out[143]:
[[1, 4, 4.0],
[1, 5, 4.5],
[1, 6, 5.0],
[2, 4, 6.0],
[2, 5, 6.5],
[2, 6, 7.0],
[3, 4, 8.0],
[3, 5, 8.5],
[3, 6, 9.0]]
一个 3 列的数据框:
In [144]: df = pd.DataFrame(alist, columns=['a','b','value'])
In [145]: df
Out[145]:
a b value
0 1 4 4.0
1 1 5 4.5
2 1 6 5.0
3 2 4 6.0
4 2 5 6.5
5 2 6 7.0
6 3 4 8.0
7 3 5 8.5
8 3 6 9.0
使用相同数据制作“网格”数据框的一种方法:
In [147]: pd.DataFrame(np.array(alist)[:,2].reshape(3,3), columns=a, index=b)
Out[147]:
1 2 3
4 4.0 4.5 5.0
5 6.0 6.5 7.0
6 8.0 8.5 9.0
糟糕的是,错误地映射了行和列;让我们转置 3x3 数组:
In [149]: pd.DataFrame(np.array(alist)[:,2].reshape(3,3).T, columns=a, index=b)
Out[149]:
1 2 3
4 4.0 6.0 8.0
5 4.5 6.5 8.5
6 5.0 7.0 9.0
我很了解numpy
;我对pandas
的经验有限。我敢肯定还有其他方法可以构建这样的框架。我的猜测是,如果你的价值函数足够复杂,迭代机制对整体运行时间的影响会很小。简单地评估每个单元格的功能将占用大部分时间。
如果您的函数可以编写为采用数组而不是标量,则无需迭代即可轻松计算值。例如:
In [171]: I,J = np.meshgrid(b,a,indexing='ij')
In [172]: X = J*2 + I*.5
In [173]: X
Out[173]:
array([[4. , 6. , 8. ],
[4.5, 6.5, 8.5],
[5. , 7. , 9. ]])
In [174]: I
Out[174]:
array([[4, 4, 4],
[5, 5, 5],
[6, 6, 6]])
In [175]: J
Out[175]:
array([[1, 2, 3],
[1, 2, 3],
[1, 2, 3]])
【讨论】:
以上是关于从 itertools 产品创建数据框的主要内容,如果未能解决你的问题,请参考以下文章