我有如下所示的列:
Data
0 A
1 Av
2 Zcef
我希望输出使用某些功能
def len_mul(a,b):
return len(a) * len(b)
这个功能可以替换,
Data A Av Zcef
A 1 2 4
Av 2 4 8
Zcef 4 8 16
我能够使用for循环,但我不想使用for循环。
我正在尝试使用pd.crosstab
,但我被困在aggfunc
。
len_mul
函数很重要,因为这是简单的示例函数。
使用您的自定义功能:
def len_mul(a,b):
return len(a) * len(b)
idx = pd.MultiIndex.from_product([df['Data'], df['Data']])
df_out = pd.Series(idx.map(lambda x: len_mul(*x)), idx).unstack()
df_out
输出:
A Av Zcef
A 1 2 4
Av 2 4 8
Zcef 4 8 16
这是来自@piRSquared SO Post
您可以将np.outer
与pd.DataFrame构造函数一起使用:
lens = df['Data'].str.len()
pd.DataFrame(np.outer(lens,lens), index = df['Data'], columns=df['Data'])
输出:
Data A Av Zcef
Data
A 1 2 4
Av 2 4 8
Zcef 4 8 16
让我们把它作为一个详细的评论。我认为这主要取决于你的len_mul
功能。如果你想和你的问题完全一样,你可以使用一些线性代数。特别是将矩阵nxq与矩阵qxm相乘得到矩阵nxm的事实。
import pandas as pd
import numpy as np
df = pd.DataFrame({"Data":["A", "Av", "Zcef"]})
# this is the len of every entries
v = df["Data"].str.len().values
# this reshape as a (3,1) matrix
v.reshape((-1,1))
# this reshape as a (1,3) matrix
v.reshape((1,-1))
#
arr = df["Data"].values
# this is the matrix multiplication
m = v.reshape((-1,1)).dot(v.reshape((1,-1)))
# your expected output
df_out = pd.DataFrame(m,
columns=arr,
index=arr)
更新
我同意Scott Boston解决方案适用于自定义功能的一般情况。但我认为您应该寻找一种可能的方法将您的函数转换为使用线性代数可以执行的操作。
这里有一些时间:
import pandas as pd
import numpy as np
import string
alph = list(string.ascii_letters)
n = 10000
data = ["".join(np.random.choice(alph,
np.random.randint(1,10)))
for i in range(n)]
data = sorted(list(set(data)))
df = pd.DataFrame({"Data":data})
def len_mul(a,b):
return len(a) * len(b)
%%time
idx = pd.MultiIndex.from_product([df['Data'], df['Data']])
df_out1 = pd.Series(idx.map(lambda x: len_mul(*x)), idx).unstack()
CPU times: user 1min 32s, sys: 10.3 s, total: 1min 43s
Wall time: 1min 43s
%%time
lens = df['Data'].str.len()
arr = df['Data'].values
df_out2 = pd.DataFrame(np.outer(lens,lens),
index=arr,
columns=arr)
CPU times: user 99.7 ms, sys: 232 ms, total: 332 ms
Wall time: 331 ms
%%time
v = df["Data"].str.len().values
arr = df["Data"].values
m = v.reshape((-1,1)).dot(v.reshape((1,-1)))
df_out3 = pd.DataFrame(m,
columns=arr,
index=arr)
CPU times: user 477 ms, sys: 188 ms, total: 666 ms
Wall time: 666 ms
明显的赢家是斯科特波士顿第二解决方案,我的速度慢了2倍。第一种解决方案分别比311x和154x慢。
我的建议是使用列表理解而不是循环来构建数组。 这样,您可以随后使用它轻松创建数据框。
用法示例:
import pandas as pd
array = ['A','B','C']
def function (X):
return X**2
L = [[function(X) for X in pd.np.arange(3)] for Y in pd.np.arange(3)]
L
>>> [[0, 1, 4], [0, 1, 4], [0, 1, 4]]
pd.DataFrame(L, columns=array, index=array)
一些文字:https://www.pythonforbeginners.com/basics/list-comprehensions-in-python
希望能帮助到你!