Python 利用条件将df转换为矩阵
是否可以将df转换为如下矩阵?给定的Python 利用条件将df转换为矩阵,python,pandas,numpy,dataframe,Python,Pandas,Numpy,Dataframe,是否可以将df转换为如下矩阵?给定的df: Name Value x 5 x 2 x 3 x 3 y 3 y 2 z 4 矩阵将是: Name 1 2 3 4 5 x 4 4 3 1 1 y 2 2 1 0 0 z 1 1 1 1 0 以下是其背后的逻辑: Name 1 2 3 4 5 (5 c
df
:
Name Value
x 5
x 2
x 3
x 3
y 3
y 2
z 4
矩阵将是:
Name 1 2 3 4 5
x 4 4 3 1 1
y 2 2 1 0 0
z 1 1 1 1 0
以下是其背后的逻辑:
Name 1 2 3 4 5 (5 columns since 5 is the max in Value)
--------------------------------------------------------------------
x 4 (since x has 4 values >= 1) 4 (since x has 4 values >= 2) 3 (since x has 3 values >= 3) 1 (since x has 1 values >= 4) 1 (since 1 x >= 5)
y 2 (since y has 2 values >= 1) 2 (since y has 2 values >= 2) 1 (since y has 1 values >= 3) 0 (since no more y >= 5) 0 (since no more y >= 5)
z 1 (since z has 1 values >= 1) 1 (since z has 1 values >= 2) 1 (since z has 1 values >= 3) 1 (since z has 1 values >= 4) 0 (since no more z >= 5)
让我知道这是否合理。我知道我必须使用排序、分组和计数,但不知道如何设置矩阵
谢谢你 这不是最漂亮的,但应该有用:
d2 = df.pivot_table(index="Name", columns="Value", aggfunc=len)
d2 = d2.reindex(range(1, df["Value"].max()+1), axis=1).fillna(0)
d2 = d2.iloc[:, ::-1].cumsum(axis=1).iloc[:, ::-1]
给我
In [115]: d2
Out[115]:
Value 1 2 3 4 5
Name
x 4.0 4.0 3.0 1.0 1.0
y 2.0 2.0 1.0 0.0 0.0
z 1.0 1.0 1.0 1.0 0.0
其中重复的
.iloc[:,::-1]
只是为了得到从右到左出现的累积和。不确定这是否是最好的方法,但您可以尝试类似的方法
import pandas as pd
import numpy as np
df = pd.DataFrame({"Name":["x","x","x","x","y","y","z"],
"Value":[5,2,3,3,3,2,4]})
mv = df["Value"].max()
out=[]
for i in range(mv):
out.append(df.groupby("Name").apply(lambda x : len(x[x["Value"]>=i+1])))
df2 = pd.concat(out, axis=1)
df2.columns = np.arange(1,mv+1)
下面是groupby的一种解决方法:
def get_counts(frame, idx):
idx = np.arange(1, idx+1)[::-1]
vc = frame['Value'].value_counts().reindex(idx)
return vc.cumsum().ffill().sort_index().fillna(0.).astype(int)
idx = df['Value'].max()
print(df.groupby('Name').apply(lambda f: get_counts(f, idx)))
Value 1 2 3 4 5
Name
x 4 4 3 1 1
y 2 2 1 0 0
z 1 1 1 1 0
这构建了一个基本上是“助手函数”的函数,它可以得到。这是一个好问题,我将使用
pd.cut
,注意,它对float也有好处:-)
可能是最快的解决方案,使用
numpy
的广播-
i = np.arange(1, df.Value.max() + 1)
j = df.Value.values[:, None] >= i
df = pd.DataFrame(j, columns=i, index=df.Name).sum(level=0)
1 2 3 4 5
Name
x 4.0 4.0 3.0 1.0 1.0
y 2.0 2.0 1.0 0.0 0.0
z 1.0 1.0 1.0 1.0 0.0
警告:作为对性能的交换,这是一种内存不足的方法。对于大数据,它可能会导致内存崩溃,因此请谨慎使用
详细信息 创建一系列值,从
1
到df.Value.max()
-
i = np.arange(1, df.Value.max() + 1)
i
array([1, 2, 3, 4, 5])
j = df.Value.values[:, None] >= i
j
array([[ True, True, True, True, True],
[ True, True, False, False, False],
[ True, True, True, False, False],
[ True, True, True, False, False],
[ True, True, True, False, False],
[ True, True, False, False, False],
[ True, True, True, True, False]], dtype=bool)
k.sum(level=0).astype(int)
1 2 3 4 5
Name
x 4 4 3 1 1
y 2 2 1 0 0
z 1 1 1 1 0
与df.值
和i
进行广播比较-
i = np.arange(1, df.Value.max() + 1)
i
array([1, 2, 3, 4, 5])
j = df.Value.values[:, None] >= i
j
array([[ True, True, True, True, True],
[ True, True, False, False, False],
[ True, True, True, False, False],
[ True, True, True, False, False],
[ True, True, True, False, False],
[ True, True, False, False, False],
[ True, True, True, True, False]], dtype=bool)
k.sum(level=0).astype(int)
1 2 3 4 5
Name
x 4 4 3 1 1
y 2 2 1 0 0
z 1 1 1 1 0
将其加载到数据帧中,并按df.Name
执行分组求和,以获得最终结果
k = pd.DataFrame(j, columns=i, index=df.Name)
k
1 2 3 4 5
Name
x True True True True True
x True True False False False
x True True True False False
x True True True False False
y True True True False False
y True True False False False
z True True True True False
如果需要将结果转换为整数,请调用.astype(int)
-
i = np.arange(1, df.Value.max() + 1)
i
array([1, 2, 3, 4, 5])
j = df.Value.values[:, None] >= i
j
array([[ True, True, True, True, True],
[ True, True, False, False, False],
[ True, True, True, False, False],
[ True, True, True, False, False],
[ True, True, True, False, False],
[ True, True, False, False, False],
[ True, True, True, True, False]], dtype=bool)
k.sum(level=0).astype(int)
1 2 3 4 5
Name
x 4 4 3 1 1
y 2 2 1 0 0
z 1 1 1 1 0
为了不必反转两次来执行求和运算,您可以按降序重新编制索引并反转一次:
.reindex(range(df.Value.max(),0,-1),axis=1)。fillna(0)。cumsum(axis=1)。iloc[:,::-1]
没什么大不了的,但您知道我为什么会得到这个运行时警告:在大于等于j=df.Value.values[:,None] >= i@TylerNG隐马尔可夫模型。。。不太确定。。。可能是南斯或INF在那里。。。需要深入研究数据以了解发生了什么。不必麻烦。我只是好奇。就这些:)