pandas 展开并转换 Dataframe ,将每一行与所有其他行进行比较

8aqjt8rx  于 2023-03-28  发布在  其他
关注(0)|答案(4)|浏览(172)

请将鲍勃的字节数组与其他所有人的字节数组进行比较。对每个人都这样做。

columns = ["pasta", "potatoes", "rice"]
data = [[1, 0, 1], [0, 1, 1], [1, 1, 1]]
index = ["tom", "jenny", "bob"]
df = pd.DataFrame(data=data, columns=columns, index=index)

# output
#        pasta  potatoes  rice
# tom        1         0     1
# jenny      0         1     1
# bob        1         1     1

数据说明:1 =喜欢列名的食物// 0不喜欢列名的食物。
我想把每个人的字节数组和其他所有人的字节数组进行比较。如果不同,则为1;0,如果没有区别。
所以希望输出看起来像

pasta potatoes rice
tom   jenny  1     1        0
tom   bob    0     1        0
jenny tom    1     1        0
jenny bob    1     0        0
bob   tom    0     1        0
bob   jenny  1     0        0

我知道bob-jenny的byte-array和jenny-bob的byte-array是一样的,但是我需要这样的byte-array。我不在乎它是一个多索引的dataframe还是两个不同的列。谢谢!

jrcvhitl

jrcvhitl1#

您可以使用itertools.permutations生成排列,然后切片和比较:

from itertools import permutations

a, b = map(list, zip(*permutations(df.index, r=2)))

out = (df.loc[a].ne(df.loc[b].to_numpy()).astype(int)
         .set_axis(pd.MultiIndex.from_arrays([a, b]))
       )

输出:

pasta  potatoes  rice
tom   jenny      1         1     0
      bob        0         1     0
jenny tom        1         1     0
      bob        1         0     0
bob   tom        0         1     0
      jenny      1         0     0

您可以轻松地使用combinations来代替permutations(总信息相同):
输出:

pasta  potatoes  rice
tom   jenny      1         1     0
      bob        0         1     0
jenny bob        1         0     0
eblbsuwk

eblbsuwk2#

首先使用MultiIndex.from_product

idx = pd.MultiIndex.from_product([df.index, df.index])
idx = idx[idx.get_level_values(0) != idx.get_level_values(1)]

或者使用itertools.permutationsMultiIndex.from_tuples的解决方案:

from itertools import permutations

idx = pd.MultiIndex.from_tuples(list(permutations(df.index, 2)))

然后使用Series.reindex和compare by DataFrame.ne,并将boolean转换为整数,以进行True/False1/0的Map:

df = df.reindex(idx, level=0).ne(df.reindex(idx, level=1)).astype(int)
print (df)
             pasta  potatoes  rice
tom   jenny      1         1     0
      bob        0         1     0
jenny tom        1         1     0
      bob        1         0     0
bob   tom        0         1     0
      jenny      1         0     0
ni65a41a

ni65a41a3#

您可以cross join和groupby()

d = df.reset_index().join(df.reset_index(),how = 'cross',lsuffix='_').set_index(['index_','index']).rename(lambda x: x.rstrip('_'),axis=1).groupby(level=0,axis=1).all()

(~d).astype(int).loc[d.index.get_level_values(0)!=d.index.get_level_values(1)]

输出:

pasta  potatoes  rice
index_ index                       
tom    jenny      1         1     0
       bob        0         1     0
jenny  tom        1         1     0
       bob        1         0     0
bob    tom        0         1     0
       jenny      1         0     0
cunj1qz1

cunj1qz14#

另一种可能的解决方案:

(pd.DataFrame((df.values != df.values[:, None]).astype(int).reshape(-1, 3), 
             index=pd.MultiIndex.from_product([df.index, df.index]))
 .set_axis(df.columns, axis=1)
 .loc[lambda x: x.index.get_level_values(0) != x.index.get_level_values(1)])

输出:

pasta  potatoes  rice
tom   jenny      1         1     0
      bob        0         1     0
jenny tom        1         1     0
      bob        1         0     0
bob   tom        0         1     0
      jenny      1         0     0

相关问题