我正在寻找一种Pythonic方法来根据DF列中的匹配数量来捕获统计数据。所以使用这个例子:
rng = pd.DataFrame( {'initial_data': ['A', 'A','A', 'A', 'B','B', 'A' , 'A', 'A', 'A','B' , 'B', 'B', 'A',]}, index = pd.date_range('4/2/2014', periods=14, freq='BH'))
test_B_mask = rng['initial_data'] == 'B'
rng['test_for_B'] = rng['initial_data'][test_B_mask]
并运行此函数以提供匹配:
def func_match(df_in,val):
return ((df_in == val) & (df_in.shift() == val)).astype(int)
func_match(rng['test_for_B'],rng['test_for_B'])
我得到以下输出:
2014-04-02 09:00:00 0
2014-04-02 10:00:00 0
2014-04-02 11:00:00 0
2014-04-02 12:00:00 0
2014-04-02 13:00:00 0
2014-04-02 14:00:00 1
2014-04-02 15:00:00 0
2014-04-02 16:00:00 0
2014-04-03 09:00:00 0
2014-04-03 10:00:00 0
2014-04-03 11:00:00 0
2014-04-03 12:00:00 1
2014-04-03 13:00:00 1
2014-04-03 14:00:00 0
Freq: BH, Name: test_for_B, dtype: int64
我可以使用func_match(rng['test_for_B'],rng['test_for_B']).sum()
之类的简单内容
返回
3
获取金额,如果值总数匹配,但有人可以帮助提供以下更细粒度的函数吗?
我猜这将是一个在函数中使用的字典,但我确信Stack Overflow上的许多有经验的编码器都用于进行这种分析,所以我很想学习如何处理这个任务。
提前感谢你提供任何帮助。
编辑:
我最初没有指定所需的输出,因为我对所有选项持开放态度,并且不想阻止任何人提供解决方案。但是,根据MaxU对所需输出的请求,这样的事情会很棒:
Matches Matches_Percent
0 match 3 30
1 match 4 40
2 match 2 20
3 match 1 10
etc
答案 0 :(得分:3)
rng = pd.DataFrame({'initial_data': ['A', 'A', 'A', 'A', 'B', 'B', 'A', 'A', 'A', 'A', 'B', 'B', 'B', 'A',]},
index = pd.date_range('4/2/2014', periods=14, freq='BH'))
bool
分配给列'test_for_B'
rng['test_for_B'] = rng['initial_data'] == 'B'
测试'B'
,最后一行不是'B'
。这表示组的开始。然后cumsum
将小组联系在一起。
contigious_groups = ((rng.initial_data == 'B') & (rng.initial_data != rng.initial_data.shift())).cumsum()
现在我groupby
我们创建了这个分组,并在每个组中sum
bool
个。这可以得到它是双倍,三倍等等。
counts = rng.loc[contigious_groups.astype(bool)].groupby(contigious_groups).test_for_B.sum()
然后使用value_counts
获取每个群组类型的频率并除以contigious_groups.max()
,因为这是一个群组的数量。
counts.value_counts() / contigious_groups.max()
3.0 0.5
2.0 0.5
Name: test_for_B, dtype: float64
答案 1 :(得分:3)
df = pd.DataFrame({'ID': ['A', 'A','A', 'A', 'B','B', 'A' , 'A', 'A', 'A','B' , 'B', 'B', 'A',]},
index = pd.date_range('4/2/2014', periods=14, freq='BH'))
df.head()
Out: ID
2014-04-02 09:00:00 A
2014-04-02 10:00:00 A
2014-04-02 11:00:00 A
2014-04-02 12:00:00 A
2014-04-02 13:00:00 B
要计算每个ID的出现次数,您可以使用pd.Series.value_counts
df['ID'].value_counts()
Out: A 9
B 5
Name: ID, dtype: int64
要计算连续出现次数,您可以执行以下操作:使用每个ID的虚拟变量来旋转表格:
df2 = df.assign(Count = lambda x: 1)\
.reset_index()\
.pivot_table('Count', columns='ID', index='index')
df2.head()
Out: ID A B
index
2014-04-02 09:00:00 1.0 NaN
2014-04-02 10:00:00 1.0 NaN
2014-04-02 11:00:00 1.0 NaN
2014-04-02 12:00:00 1.0 NaN
2014-04-02 13:00:00 NaN 1.0
以下函数计算连续匹配的数量:
df2.apply(lambda x: x.notnull()\
.groupby(x.isnull().cumsum()).sum())
Out:
ID A B
0 4.0 NaN
1 0.0 0.0
2 4.0 0.0
3 0.0 0.0
4 0.0 2.0
5 1.0 0.0
6 NaN 0.0
7 NaN 0.0
8 NaN 3.0
9 NaN 0.0
我们只需按ID和值进行分组:
df2.apply(lambda x: x.notnull().groupby(x.isnull().cumsum()).sum())\
.unstack()\
.reset_index()\
.groupby(['ID', 0]).count()\
.reset_index()\
.pivot_table(values='level_1', index=0, columns=['ID']).fillna(0)
Out:
ID A B
0
0.0 3.0 7.0
1.0 1.0 0.0
2.0 0.0 1.0
3.0 0.0 1.0
4.0 2.0 0.0
例如,前面的表格A
有2个连续4场比赛。
要获得百分比,请添加.pipe(lambda x: x/x.values.sum())
:
Out:
ID A B
0
0.0 0.200000 0.466667
1.0 0.066667 0.000000
2.0 0.000000 0.066667
3.0 0.000000 0.066667
4.0 0.133333 0.000000