【问题标题】:Assign running count to a new column in groups of 3 pandas将运行计数分配给 3 个熊猫组中的新列
【发布时间】:2019-02-17 18:21:25
【问题描述】:

我正在尝试根据另一个 2 中的值在 pandas df 中分配一个新的 column

在下面的 df 中,对于Location (Home, Away etc) 中的每个单独值,我想为Day 中的第一个3 对应的unique 值分配一个递增的integer

import pandas as pd
import numpy as np

d = ({
    'Time' : ['7:00:00','8:00:00','9:00:00','11:00:00','12:00:00','1:00:00','2:00:00','3:00:00'],                         
    'Day' : ['Mon','Tues','Wed','Thurs','Fri','Thurs','Fri','Sat'],                 
    'Location' : ['Home','Home','Home','Away','Away','Home','Home','Home'],              
    })

df = pd.DataFrame(data=d)

#Assign values from Home
mask = df['Location'] == 'Home'
df1 = df[mask].drop_duplicates('Day')
d = dict(zip(df1['Day'], np.arange(len(df1)) // 3 + 1))

df.loc[mask, 'Assign'] = df.loc[mask, 'Day'].map(d)

#Assign values from Away
mask = df['Location'] == 'Away'
df1 = df[mask].drop_duplicates('Day')
d = dict(zip(df1['Day'], np.arange(len(df1)) // 3 + 1))

df.loc[mask, 'Assign'] = df.loc[mask, 'Day'].map(d)

输出:

       Time    Day Location  Assign
0   7:00:00    Mon     Home     1.0
1   8:00:00   Tues     Home     1.0
2   9:00:00    Wed     Home     1.0
3  11:00:00  Thurs     Away     1.0
4  12:00:00    Fri     Away     1.0
5   1:00:00  Thurs     Home     2.0
6   2:00:00    Fri     Home     2.0
7   3:00:00    Sat     Home     2.0

预期输出:

       Time    Day Location Assign
0   7:00:00    Mon     Home    1.0
1   8:00:00   Tues     Home    1.0
2   9:00:00    Wed     Home    1.0
3  11:00:00  Thurs     Away    2.0
4  12:00:00    Fri     Away    2.0
5   1:00:00  Thurs     Home    3.0
6   2:00:00    Fri     Home    3.0
7   3:00:00    Sat     Home    3.0

【问题讨论】:

  • 'Location' 中的连续值的数量最多为 3?还是可以重复超过 3 次?
  • 这可能会如何发挥作用存在歧义。请展示一个稍微大一点的例子来解释逻辑。比如,如果第四排是星期四在家会怎样?我还有其他几个问题,但是把它们都写下来需要太多时间。你应该做这项工作。
  • @piRSquared,在这种情况下,它仍然是 2,因为它超过了 3 unique 值。然后Row 5 将变为3
  • @gyoza,它可以重复。所以Mon, Tues, Wed 将是1Thurs, Fri, Sat 将是 2。它也不必订购。例如,对于 1,它可能是 Mon, Fri, Sat,对于 2,它可能是 Sun, Wed, Mon。这只是第一个 3 unique

标签: python pandas dataframe assign


【解决方案1】:

我认为需要GroupBy.apply 的自定义函数,然后通过factorize 将值转换为数值:

def f(x):
    x1 = x.drop_duplicates('Day')
    d = dict(zip(x1['Day'], np.arange(len(x1)) // 3 + 1))
    x['new'] = x['Day'].map(d)
    return x

df = df.groupby('Location', sort=False, group_keys=False).apply(f)
df['new'] = pd.factorize(df['new'].astype(str) + df['Location'])[0] + 1
print (df)
       Time    Day Location  new
0   7:00:00    Mon     Home    1
1   8:00:00   Tues     Home    1
2   9:00:00    Wed     Home    1
3  11:00:00  Thurs     Away    2
4  12:00:00    Fri     Away    2
5   1:00:00  Thurs     Home    3
6   2:00:00    Fri     Home    3
7   3:00:00    Sat     Home    3

unique 代替drop_duplicates 的另一个类似解决方案:

def f(x):
    u = x['Day'].unique()
    d = dict(zip(u, np.arange(len(u)) // 3 + 1))
    x['new'] = x['Day'].map(d)
    return x

df = df.groupby('Location', sort=False).apply(f)

s = df['new'].astype(str) + df['Location']
df['new'] = pd.factorize(s)[0] + 1
print (df)
      Day Location  new
0     Mon     Home    1
1    Tues     Home    1
2     Wed     Away    2
3     Wed     Home    1
4   Thurs     Away    2
5   Thurs     Home    3
6     Fri     Home    3
7     Mon     Home    1
8     Sat     Home    3
9     Fri     Away    2
10    Sun     Home    4

【讨论】:

  • 这是在 jezrael 上的位置,但我们可以失去 drop_duplicates 吗?如果 [Day][Location] 中相同的两个值重复,我想分配相同的 [new]
  • @Maxibon - 请立即检查解决方案。
  • 你是明星。我有一个更复杂的数据集,这个代码实际上可以处理。我试图在这里简化它。如果您想在此处发布此答案,我将重复此问题。链接为:stackoverflow.com/questions/52215236/…
  • @Maxibon - 我认为没有重复的理由,不确定是否有时间解决您的链接问题,但我可以试试。
  • @Maxibon - 所以添加的解决方案有点改变 - unique 应该更快,最好测试一下。
猜你喜欢
  • 2022-08-04
  • 2021-01-29
  • 2018-12-02
  • 2015-04-14
  • 2018-02-16
  • 2021-07-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多