从 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>,生成的输出行/列包含 ab 中的元素。

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 是否采用标量 ij?所以它必须在创建数据框之前或之后迭代地应用? 不,函数非常复杂,但每次迭代 (i, j) 的最终结果是一个包含许多列的数据帧。然后我从列中选择一个值 有两个问题,1) 为ab 的笛卡尔积生成x_value,以及2) 用ab 列排列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 产品创建数据框的主要内容,如果未能解决你的问题,请参考以下文章

itertools 组合和产品 [关闭]

使用 itertools 创建 numpy 数组

python itertools 产品重复到大

按数字顺序排列 itertools 产品

如何嵌套 itertools 产品?

Itertools 产品不重复重复