假设我有一个DataFrame
,看起来像:
import pandas as pd
import numpy as np
df = pd.DataFrame({'Week' : [1, 2, 1, 2, 1, 2, 1, 2],
'Rabbits' : np.random.randn(8),
'Donkeys' : np.random.randn(8) * 4,
'Mice' : np.random.randn(8) * 4})
哪个使df
:
然后我要根据天分组,并每天进行一次基本的corr
测试:
week_group = df.groupby('Week')
week_group = week_group[df.columns.difference(["Week"])]
week_cor = week_group.corr()
第1周和第2周将week_cor
设为MultiIndex
,
因此,现在我要执行以下操作:我想基于“两个” DataFrame
创建一个DataFrame
。详细说明:让我们将第1周视为df1
,将第2周视为df2
。现在,我们考虑一下df1
entry1
中的一个条目和df2
,entry2
中的一个条目。结果DataFrame
的构造如下:
def collapse(entry1, entry2):
if abs(entry1) >= 0.6 and abs(entry2) >= 0.6:
return 1
else:
return 0
所以在这种情况下,我想要类似的东西:
Donkeys Mice Rabbits
Donkeys 1.000000 0.000000 0.000000
Mice 0.000000 1.000000 0.000000
Rabbits 0.000000 0.000000 1.000000
在python中,我通常会执行reduce
嵌套列表,但是它不起作用:
from functools import reduce
def collapse(entry1, entry2):
if abs(entry1) >= 0.6 and abs(entry2) >= 0.6:
return 1
else:
return 0
reduce(collapse, week_cor)
哪个给:
TypeError: bad operand type for abs(): 'str'
这很有意义,因为它有点像是带有字符串键的数组。
我可能会误解pandas
的目的,但是我觉得这种在reduce
上执行类似MultiIndex
的操作的想法会很普遍,并且pandas
将有办法做到这一点。如果我对此假设有误,请纠正我;否则,请问纠正MultiIndex
的标准缩减方法是什么?
通常:我要使用一个DataFrame
,然后按某个时间点对数据进行分组。然后,我将执行一个操作(在本示例中为corr
)以根据时间获得MultiIndex
。我想以类似于MultiIndex
在Python中创建列表的方式“折叠”或减少reduce
。结果,我将MultiIndex
减少为DataFrame
。
答案 0 :(得分:3)
在这种情况下,我认为您可以在groupby
的第一级上再做一个week_cor
,检查所有绝对值是否都大于或等于0.6
print(week_cor)
Donkeys Mice Rabbits
Week
1 Donkeys 1.000000 -0.118953 -0.235307
Mice -0.118953 1.000000 0.803987
Rabbits -0.235307 0.803987 1.000000
2 Donkeys 1.000000 0.229929 -0.593603
Mice 0.229929 1.000000 -0.645369
Rabbits -0.593603 -0.645369 1.000000
week_cor.groupby(level=1).apply(lambda x: x.abs().ge(0.6).all())
Donkeys Mice Rabbits
Donkeys True False False
Mice False True True
Rabbits False True True
答案 1 :(得分:1)
因此,我认为最简单的解决方案是使用pandas.DataFrame.reset_index
删除MultiIndex,如下所示:
week_cor = week_cor.reset_index()
现在,您可以在Week
列中选择所需的相关子集。这样,您可以更轻松地对它们两个执行进一步的操作。这是一个numpy
解决方案,您也许可以以此为基础。
cols = ['Donkeys','Mice','Rabbits']
df1 = week_cor[week_cor['Week'] == 1][cols].values #ndarray
df2 = week_cor[week_cor['Week'] == 2][cols].values #ndarray
def collapse(A, B):
return np.where((A >= 0.6) & (B >= 0.6), 1, 0)
new_df = pd.DataFrame(collapse(df1, df2), index=cols, columns=cols)
让我知道您是否可以reduce
上班,因为我有兴趣了解。
答案 2 :(得分:0)
注意:我在看到Ben.T的评论之前就发布了这个答案,他的方法更加简洁,应该使用。
我在扩展Dascienz的答案以使其更笼统:
正如达西恩茨所说:
因此,我认为最简单的解决方案是使用
删除MultiIndexpandas.DataFrame.reset_index
因此,来自:
animal_group = week_cor.reset_index()
我们得到:
然后可以通过"level_1"
再次将其分组,以进行说明(看起来像片):
animal_group = week_cor.reset_index().groupby("level_1")
animal_group.get_group("Donkeys")
给予:
这可以使用agg
来减少(尽管我不确定这是否是最好的选择),而"Week"
列可以放在最后:
from math import floor
def collapse(x):
x = x.map(lambda elem: 1 if abs(elem) > 0.6 else 0)
# A little bit of a math trick here...
return floor(x.abs().sum() / 2)
animal_group.agg(collapse).drop("Week", axis=1)
仍然显得有些冗长(或者我对Python期望太高了)。但最后:
根据需要。