根据课程持续时间重复行

时间:2017-08-19 05:54:04

标签: pandas

我有一个需要重复的数据框。

from io import StringIO
import pandas as pd

audit_trail = StringIO('''
course_id AcademicYear_to months TotalFee
260 2017 24 100
260 2018 12 140
274 2016 36 300
274 2017 24 340
274 2018 12 200
285 2017 24 300
285 2018 12 200
''')

df11 = pd.read_csv(audit_trail, sep=" "  )

对于课程编号260,每年有2个条目。 2017年和2018年。我需要重复月份组的年份。 我将再获得2行,2018年为24个月,2017年为12个月。最终数据框将如下所示......

audit_trail = StringIO('''
course_id AcademicYear_to months TotalFee
260 2017 24 100
260 2018 24 100
260 2017 12 140
260 2018 12 140
274 2016 36 300
274 2017 36 300
274 2018 36 300
274 2016 24 340
274 2017 24 340
274 2018 24 340
274 2016 12 200
274 2017 12 200
274 2018 12 200
285 2017 24 300
285 2018 24 300
285 2017 12 200
285 2018 12 200
''')

df12 = pd.read_csv(audit_trail, sep=" "  )

我试图将相同的数据帧连续两次,但这并没有解决问题。我需要改变年份和36个月,数据需要重复3次。

pd.concat([df11, df11])

按对象分组将返回年份。我只需要在每组中加入原始数据框。

df11.groupby('course_id')['AcademicYear_to'].apply(list)

260          [2017, 2018]
274    [2016, 2017, 2018]
285          [2017, 2018]

如果记录与年数匹配,则简单连接可以起作用。对于例如课程ID 274有48个月,285有24个月的持续时间,分别有3个,2个条目。问题是课程编号260,这是24个月课程,但只有1个条目。 加入不会返回该课程的第二年

df11=pd.read_csv('https://s3.amazonaws.com/todel162/myso.csv')

df11.course_id.value_counts()
274    3
285    2
260    1

df=df11.merge(df11[['course_id']], on='course_id')

df.course_id.value_counts()
274    9
285    4
260    1

是否可以编写一个也会考虑月数的查询?

以下查询将返回简单连接不会返回预期结果的记录。

df11=pd.read_csv('https://s3.amazonaws.com/todel162/myso.csv')
df11['m1']=df11.groupby('course_id').course_id.transform( lambda x: x.count() * 12) 
df11.query( 'm1  !=  duration_inmonths') 

df11.course_id.value_counts()
274    3
285    2
260    1

df=df11.merge(df11[['course_id']], on='course_id')

df.course_id.value_counts()
274    9
285    4
260    1

此情况下的预期计数为

274    6
285    4
260    2

这是因为即使id 274有3年,课程持续时间也只有24个月。即使持续时间为24个月只有260条记录,它也应该返回2条记录。 (本年度一次,当前年份+ 1次)

2 个答案:

答案 0 :(得分:2)

不漂亮!

def f(x):
    idx = x.index.remove_unused_levels()
    idx = pd.MultiIndex.from_product(idx.levels, names=idx.names)
    return x.reindex(idx)

df11.set_index(['months', 'AcademicYear_to']) \
    .groupby('course_id').TotalFee.apply(f) \
    .groupby(level=[0, 1]).transform('first') \
    .astype(df11.TotalFee.dtype).reset_index()

    course_id  months  AcademicYear_to  TotalFee
0         260      24             2017       100
1         260      24             2018       100
2         260      12             2017       140
3         260      12             2018       140
4         274      12             2016       200
5         274      12             2017       200
6         274      12             2018       200
7         274      24             2016       340
8         274      24             2017       340
9         274      24             2018       340
10        274      36             2016       300
11        274      36             2017       300
12        274      36             2018       300
13        285      24             2017       300
14        285      24             2018       300
15        285      12             2017       200
16        285      12             2018       200

答案 1 :(得分:2)

IIUC我们merge df11可以自己:

In [14]: df11.merge(df11[['course_id']], on='course_id')
Out[14]:
    course_id  AcademicYear_to  months  TotalFee
0         260             2017      24       100
1         260             2017      24       100
2         260             2018      12       140
3         260             2018      12       140
4         274             2016      36       300
5         274             2016      36       300
6         274             2016      36       300
7         274             2017      24       340
8         274             2017      24       340
9         274             2017      24       340
10        274             2018      12       200
11        274             2018      12       200
12        274             2018      12       200
13        285             2017      24       300
14        285             2017      24       300
15        285             2018      12       200
16        285             2018      12       200