【问题标题】:Counting the number of consecutive occurences of numbers in dataframe with multi index daily data使用多索引每日数据计算数据框中数字连续出现的次数
【发布时间】:2021-05-03 13:47:24
【问题描述】:

这里已经回答了这个问题的一个版本(但是它使用的是分钟频率的数据)。

Counting the number of consecutive occurences of numbers in dataframe with multi index

我有一个数据框,它有一个多索引(股票代码和日期),其中有一个包含 1 和 0 的虚拟列,我想计算每只股票的每一行中 1 或 0 出现的次数“虚拟”列,每次从 1 开始,向上计数为 1,向下计数为 0 我在下面有一个示例,其中“计数器”列代表我想要创建的内容:

df = pd.DataFrame(  {
'stock': ['AAPL', 'AAPL', 'AAPL','AAPL', 'MSFT', 'MSFT','MSFT', 'MSFT'], 
'datetime': ['2015-01-02', '2015-01-03', '2015-01-04', '2015-01-05', '2015-01-02', '2015-01-03', '2015-01-04', '2015-01-05'],
'Dummy': [0, 0, 1, 1, 1,1, 0, 1],
'Counter': [-1, -2, 1, 2, 1, 2, -1, 1]})
df['datetime'] = pd.to_datetime(df['datetime'])
df.set_index(['stock', 'datetime'], inplace =True)

【问题讨论】:

  • 对于 MSFT - 2015-01-04 - 0(Dummy),Counter 应该是 1 还是 -1?
  • 你说得对,应该是-1,我修好了。
  • @NiccolaTartaglia 你能解释一下为什么2015-01-04上符号MSFT的Counter的值是-1,我认为这应该是1?
  • 这是因为 Dummy 为 0,所以它是 MSFT 之前为正之后的第一个 0。这就是为什么它应该是-1。

标签: pandas dataframe pandas-groupby


【解决方案1】:

我们可以使用带有cumsum 的布尔掩码来识别Dummy 列中的值保持不变的连续行块,然后用-1 后跟@ 掩码Dummy 列中的0 987654326@和cumsum计算Counter

s = df['Dummy']
m = s.ne(s.shift())
df['Counter'] = s.mask(s.eq(0), -1).groupby(['stock', m.cumsum()]).cumsum()

                  Dummy  Counter
stock datetime                  
AAPL  2015-01-02      0       -1
      2015-01-03      0       -2
      2015-01-04      1        1
      2015-01-05      1        2
MSFT  2015-01-02      1        1
      2015-01-03      1        2
      2015-01-04      0       -1
      2015-01-05      1        1

【讨论】:

  • 谢谢。所以这适用于我提供的数据框示例,但不知何故它不适用于我的实际数据框。我试图找出原因,一些小事似乎有所不同。
  • @NiccolaTartaglia IMO 这应该可以正常工作,但是您能否用一些示例行编辑您的问题,您会得到不同的结果?
  • 我同意,并且在我上面给出的示例中它确实工作得很好。我试图找出我的实际数据框中到底有什么不同,某处似乎有一些细微的差别。
  • @NiccolaTartaglia 你确定你的虚拟列只包含0's 和1's?也许你可以尝试用s.mask(s.ne(1), -1)替换条件s.mask(s.eq(0), -1)
  • 谢谢@tdy 没错,mask 和where 之间没有太大区别,mask 替换了条件成立的值True 而where 替换了条件成立的值持有False
【解决方案2】:

尝试类似:

import pandas as pd

df = pd.DataFrame({
    'stock': ['AAPL', 'AAPL', 'AAPL', 'AAPL',
              'MSFT', 'MSFT', 'MSFT', 'MSFT'],
    'datetime': ['2015-01-02', '2015-01-03',
                 '2015-01-04', '2015-01-05',
                 '2015-01-02', '2015-01-03',
                 '2015-01-04', '2015-01-05'],
    'Dummy': [0, 0, 1, 1, 1, 1, 0, 1]})
df['datetime'] = pd.to_datetime(df['datetime'])
df.set_index(['stock', 'datetime'], inplace=True)

# Group Consecutive 1 and 0 groups in each stock together
df['group'] = df.groupby('stock')['Dummy'] \
    .transform(lambda g: g.ne(g.shift()).cumsum())
# Set Value Placeholder in Counter 1 -> 1, 0 -> -1
df['Counter'] = df['Dummy'].apply(lambda x: 1 if x == 1 else -1)
# Get cumsum from each stock and group
df['Counter'] = df.groupby(['stock', 'group'])['Counter'].cumsum().astype(int)
# Drop Group Column
df = df.drop(columns='group')

# For Display
print(df.to_string())

输出:

虚拟计数器 股票日期时间 苹果 2015-01-02 0 -1 2015-01-03 0 -2 2015-01-04 1 1 2015-01-05 1 2 微软 2015-01-02 1 1 2015-01-03 1 2 2015-01-04 0 -1 2015-01-05 1 1

【讨论】:

    【解决方案3】:

    感谢大家的贡献。因此,Henry 的 Shubham 解决方案都适用于我在上面发布的示例数据帧,但在我的实际数据帧中,只有 Henry 的工作符合预期,Shubham 的方法只产生 1s 和 -1s,但它们并没有增加。我还根据上面链接的上一篇文章中的解决方案尝试了以下方法,它也仅适用于示例数据框,但不适用于我的实际数据框(同样的问题,1 和 -1 没有增加):

    m = df.dummy.diff().ne(0).cumsum()
    counters = df.groupby([df.index.get_level_values(0),  
                       m]).cumcount()+1
    df['Counter'] = np.where(df['dummy']==0, -1, 1) * counters
    

    所以我一定是在示例数据框上犯了一些错误,这似乎与我的实际数据框有所不同。我会设法弄清楚并报告。

    【讨论】:

      【解决方案4】:

      我终于弄清楚了问题所在。我上面的数据框示例与我的实际数据框不同,因为我的实际数据框的排序方式不同。也就是说,它不是按股票而是按天分组的,所以它看起来像这样:

      df = pd.DataFrame(  {
      'stock': ['AAPL', 'MSFT','AAPL', 'MSFT', 'AAPL', 'MSFT','AAPL', 'MSFT', ], 
      'datetime': ['2015-01-02', '2015-01-02', '2015-01-03', '2015-01-03', '2015-01-04', '2015-01-04', '2015-01-05', '2015-01-05'],
      'Dummy': [0, 0, 1, 1, 1,1, 0, 1],
      'Counter': [-1, -2, 1, 2, 1, 2, -1, 1]})
      df['datetime'] = pd.to_datetime(df['datetime'])
      df.set_index(['stock', 'datetime'], inplace =True)
      

      这就是为什么 Henry 的解决方案适用于两者,而 Shubham 的解决方案只适用于我在原始帖子中提供的示例。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-05-22
        • 1970-01-01
        • 1970-01-01
        • 2017-12-05
        • 1970-01-01
        • 2019-05-13
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多