基于数据框列

时间:2016-07-07 09:06:24

标签: python pandas dataframe

我正在寻找一种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

获取金额,如果值总数匹配,但有人可以帮助提供以下更细粒度的函数吗?

  • 看到单个匹配的数量和百分比。
  • 看到两场连续比赛的次数和百分比(在此示例中,最多n次匹配,仅为3场比赛,2014-04-02 11:00:00至13:00:00)。

我猜这将是一个在函数中使用的字典,但我确信Stack Overflow上的许多有经验的编码器都用于进行这种分析,所以我很想学习如何处理这个任务。

提前感谢你提供任何帮助。

编辑:

我最初没有指定所需的输出,因为我对所有选项持开放态度,并且不想阻止任何人提供解决方案。但是,根据MaxU对所需输出的请求,这样的事情会很棒:

  Matches       Matches_Percent
0 match    3       30
1 match    4       40
2 match    2       20
3 match    1       10
etc

2 个答案:

答案 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