0

我有一个以列表为值的数据框。

index=pd.MultiIndex.from_product([["file1", "file2", "file3"], ["a", "b"]])
index.names = ['file', 'name']
data = [
    [[1,1],[0,0]],
    [[],[]],
    [[2,2,2],[7]],
    [[],[]],
    [[1],[4, 4]],    
    [[],[]],
]
df = pd.DataFrame(data, index=index, columns=['col1', 'col2'])
df

df

                col1    col2
file    name        
file1   a      [1, 1]   [0, 0]
        b       []      []
file2   a    [2, 2, 2]  [7]
        b       []      []
file3   a       [1]     [4, 4]
        b       []      []

我想在每行和其他行的串联之间进行分组name并运行 Kolmogorov-Smirnov 测试 ( )。scipy.stats.ks_2samp名称的示例a{file1,a}== [1,1]。其他人的串联{file2,a}+ {file3,a}== [2,2,2]+ [1]== [2,2,2,1]。他们之间的 KStest 是stats.ks_2samp([1,1], [2,2,2,1])== 0.75。我怎样才能得到下面的预期结果(手动完成)?

               col1     col2
file    name        
file1   a       0.75    1.0
        b       NaN     NaN
file2   a       1.0     1.0
        b       NaN     NaN
file3   a       0.6     0.66
        b       NaN     NaN

如果这个问题太临时,我很抱歉。

下面是我的尝试。我无法弄清楚如何优雅地将目标行从其他行中排除。

df.groupby(['name']).apply(
    lambda per_name_df: per_name_df.apply(
        lambda per_column: per_column.apply(
            lambda cell: stats.ks_2samp(cell, np.concatenate(per_column.to_numpy())) if cell else cell)))

4

1 回答 1

1

...在单行和其他行的串联之间进行测试

由于您没有特别指定哪些行,我将给您一个示例来测试第一行和所有剩余行之间的情况:

from scipy.stats import ks_2samp
def ks(a, b):
    b = [el for li in b for el in li]
    if a and b:
        return ks_2samp(a, b)[0]

df.groupby(df.index.get_level_values('name')).col1.apply(lambda x: ks(x[0],x[1:].to_list()))

结果:

name
a    0.75
b     NaN
Name: col1, dtype: float64


已编辑问题的更新

...在每一行和其他行的串联之间进行测试

def ks_all(a):
    a = a.to_list()
    return [ks(a[i],a[:i]+a[i+1:]) for i in range(0,len(a))]

df.groupby(df.index.get_level_values('name')).transform(ks_all)

结果:

            col1      col2
file  name                
file1 a     0.75  1.000000
      b      NaN       NaN
file2 a     1.00  1.000000
      b      NaN       NaN
file3 a     0.60  0.666667
      b      NaN       NaN
于 2019-10-10T14:46:36.443 回答