Python 两个数据帧之间的矢量化
我一直在试图找到一种方法,在df1的每一行上实现levenes测试,每一行df2定义要拆分的组。例如,每次运行levenes测试时,df1的第一行将按df2的每一行分组。显然,我可以使用嵌套循环实现它,例如(必须包括if语句,因为并非所有行都包含所有组):Python 两个数据帧之间的矢量化,python,pandas,vectorization,Python,Pandas,Vectorization,我一直在试图找到一种方法,在df1的每一行上实现levenes测试,每一行df2定义要拆分的组。例如,每次运行levenes测试时,df1的第一行将按df2的每一行分组。显然,我可以使用嵌套循环实现它,例如(必须包括if语句,因为并非所有行都包含所有组): 这个解决方案不是特别优雅,而且有点脆弱,这意味着它在某些边缘情况下会失败。但是,如果你的数据没有任何异常情况,它就会起作用 首先,此解决方案假定df1和df2中的id列是同构的(G1=S1等)。其次,该解决方案假设只有2或3组数据可以运行Le
这个解决方案不是特别优雅,而且有点脆弱,这意味着它在某些边缘情况下会失败。但是,如果你的数据没有任何异常情况,它就会起作用 首先,此解决方案假定
df1
和df2
中的id
列是同构的(G1
=S1
等)。其次,该解决方案假设只有2或3组数据可以运行Levene的测试。(对于您的示例数据也是如此。)第三,您的示例数据没有太多数据,有时这会导致Levene测试失败-在这些情况下,Scipy会抱怨(尽管它只返回Inf
并完成执行)
简而言之,程序是:
melt()
df1
和df2
groupby
创建分组值列表lev()
DF1-ID DF2-ID Lev.stat Lev.pvalue
G1 S1 float float
G1 S2 float float
G1 S3 float float
G1 S4 float float
G2 S1 float float
.
.
.
G4 S4 float float
下一步:
# merge data
df2.IDs = df2.IDs.str.replace("S", "G")
merged = df1.melt(id_vars="IDs").merge(df2.melt(id_vars="IDs"), on=["IDs", "variable"])
# group values into lists
lev_data = merged.groupby(["IDs", "value_y"]).value_x.agg(list).reset_index()
lev_data
IDs value_y value_x
0 G1 1 [102.2, 52.1]
1 G1 2 [112.8, 32.2]
2 G2 0 [1290.3]
3 G2 1 [1910.4]
4 G2 2 [2310.4, 2210.1]
5 G3 1 [123.4, 121.4, 155.2]
6 G3 2 [36.3]
7 G4 0 [213.0, 212.3]
8 G4 1 [188.2]
9 G4 2 [244.7]
10 G5 1 [1333.5, 1987.1]
11 G5 2 [1234.2, 1271.2]
输出:
# run lev() on two- or three-group sets
def do_lev(vals):
if len(vals) == 2:
return lev(vals.iloc[0,2], vals.iloc[1,2])
return lev(vals.iloc[0,2], vals.iloc[1,2], vals.iloc[2,2])
lev_data.groupby("IDs").apply(do_lev)
注意:完全向量化在某种程度上被阻止,因为每个样本都要单独输入,而不是接受向量列表。这意味着需要将样本逐个分解并输入
lev()
,这使矢量化变得复杂。您在这里的预期输出是什么?@asongtoruin我已将预期输出添加到问题中。请注意,它是一个简化版本,S1和G1实际上是多个描述符cols.G1!=S1。对于长表格式,您需要类似于,G-IDs-ID value\u y value\u x
的标题。因此,第1行将是g1s11[float,float]
。第二行是G1 S1 2[float,float]
,第三行是G1 S2 0[float]
,这有意义吗?我已经用预期结果更新了我的问题,以帮助澄清它。你认为写我自己的能够矢量化的levene函数值得吗?我计算过我要进行4.7x10^11堤坝测试。。。
# merge data
df2.IDs = df2.IDs.str.replace("S", "G")
merged = df1.melt(id_vars="IDs").merge(df2.melt(id_vars="IDs"), on=["IDs", "variable"])
# group values into lists
lev_data = merged.groupby(["IDs", "value_y"]).value_x.agg(list).reset_index()
lev_data
IDs value_y value_x
0 G1 1 [102.2, 52.1]
1 G1 2 [112.8, 32.2]
2 G2 0 [1290.3]
3 G2 1 [1910.4]
4 G2 2 [2310.4, 2210.1]
5 G3 1 [123.4, 121.4, 155.2]
6 G3 2 [36.3]
7 G4 0 [213.0, 212.3]
8 G4 1 [188.2]
9 G4 2 [244.7]
10 G5 1 [1333.5, 1987.1]
11 G5 2 [1234.2, 1271.2]
# run lev() on two- or three-group sets
def do_lev(vals):
if len(vals) == 2:
return lev(vals.iloc[0,2], vals.iloc[1,2])
return lev(vals.iloc[0,2], vals.iloc[1,2], vals.iloc[2,2])
lev_data.groupby("IDs").apply(do_lev)
IDs
G1 (1.84254995447e+31, 5.42726126677e-32) # (test statistic, p-value)
G2 (inf, 0.0)
G3 (0.300123996469, 0.638777548242)
G4 (inf, 0.0)
G5 (inf, 0.0)
dtype: object