Python 熊猫:将列中的列表转换为行

Python 熊猫:将列中的列表转换为行,python,pandas,transpose,date-range,Python,Pandas,Transpose,Date Range,所以我有熊猫数据框df_日期如下 PERSON_ID MIN_DATE MAX_DATE 0 000099-48 2016-02-01 2017-03-20 1 000184 2016-02-05 2017-01-19 2 000461-48 2016-03-07 2017-03-20 3 000791-48 2016-02-01 2017-03-07 4 000986-48 2016-02-01 2017-03-17 5 001617 2016-02-01

所以我有熊猫数据框df_日期如下

   PERSON_ID   MIN_DATE   MAX_DATE
0  000099-48 2016-02-01 2017-03-20
1     000184 2016-02-05 2017-01-19
2  000461-48 2016-03-07 2017-03-20
3  000791-48 2016-02-01 2017-03-07
4  000986-48 2016-02-01 2017-03-17
5     001617 2016-02-01 2017-02-20
6  001768-48 2016-02-01 2017-03-20
7     001937 2016-02-01 2017-03-17
8  002223-48 2016-02-04 2017-03-16
9  002481-48 2016-02-05 2017-03-17
我正在尝试将最小值和最大值之间的所有日期添加为每个人的ID行。下面是我尝试的内容

df_dates.groupby('PERSON_ID').apply(lambda x: pd.date_range(x['MIN_DATE'].values[0], x['MAX_DATE'].values[0]))
但我从中得到的是,有没有任何方法可以将序列转换成每个人ID的行?或者其他更好的方法

PERSON_ID
0-L2ID        DatetimeIndex(['2016-08-05', '2016-08-06', '20...
0-LlID        DatetimeIndex(['2016-02-03', '2016-02-04', '20...
000099-48     DatetimeIndex(['2016-02-01', '2016-02-02', '20...
000184        DatetimeIndex(['2016-02-05', '2016-02-06', '20...
000276        DatetimeIndex(['2016-02-01', '2016-02-02', '20...
000461-48     DatetimeIndex(['2016-03-07', '2016-03-08', '20...
000493-48     DatetimeIndex(['2016-02-01', '2016-02-02', '20...
000615-48     DatetimeIndex(['2016-02-02', '2016-02-03', '20...
000791-48     DatetimeIndex(['2016-02-01', '2016-02-02', '20...
000986-48     DatetimeIndex(['2016-02-01', '2016-02-02', '20...
dtype: object
以下是我正在努力实现的目标:

PERSON_ID   Date
000099-48   2/1/2016
000099-48   2/2/2016
000099-48   2/3/2016
000099-48   2/4/2016
:
:
000099-48   3/18/2016
000099-48   3/19/2016
000099-48   3/20/2016
000184  2/5/2016
000184  2/6/2016
000184  2/7/2016
:
:
000184  1/17/2017
000184  1/18/2017
000184  1/19/2017

选项1

d = pd.concat({
        p: pd.Series(pd.date_range(s, e)) for i, p, s, e in df.itertuples()
    })

d.rename_axis(
    ['PERSON_ID', None]
).reset_index('PERSON_ID', name='Date').reset_index(drop=True)

      PERSON_ID       Date
0     000099-48 2016-02-01
1     000099-48 2016-02-02
...
414      000184 2016-02-05
415      000184 2016-02-06
...
764   000461-48 2016-03-07
765   000461-48 2016-03-08
...
1143  000791-48 2016-02-01
1144  000791-48 2016-02-02
...
1544  000986-48 2016-02-01
1545  000986-48 2016-02-02
...
1955     001617 2016-02-01
1956     001617 2016-02-02
...
2341  001768-48 2016-02-01
2342  001768-48 2016-02-02
...
2755     001937 2016-02-01
2756     001937 2016-02-02
...
lol = [pd.date_range(t.MIN_DATE, t.MAX_DATE).tolist() for t in df.itertuples()]
lns = [len(l) for l in lol]
pd.DataFrame(dict(
        PERSON_ID=df.PERSON_ID.values.repeat(lns), Date=np.concatenate(lol)
    ))[['PERSON_ID', 'Date']]

      PERSON_ID       Date
0     000099-48 2016-02-01
1     000099-48 2016-02-02
...
414      000184 2016-02-05
415      000184 2016-02-06
...
764   000461-48 2016-03-07
765   000461-48 2016-03-08
...
1143  000791-48 2016-02-01
1144  000791-48 2016-02-02
...
1544  000986-48 2016-02-01
1545  000986-48 2016-02-02
...
1955     001617 2016-02-01
1956     001617 2016-02-02
...
2341  001768-48 2016-02-01
2342  001768-48 2016-02-02
...
2755     001937 2016-02-01
2756     001937 2016-02-02
...
选项2

d = pd.concat({
        p: pd.Series(pd.date_range(s, e)) for i, p, s, e in df.itertuples()
    })

d.rename_axis(
    ['PERSON_ID', None]
).reset_index('PERSON_ID', name='Date').reset_index(drop=True)

      PERSON_ID       Date
0     000099-48 2016-02-01
1     000099-48 2016-02-02
...
414      000184 2016-02-05
415      000184 2016-02-06
...
764   000461-48 2016-03-07
765   000461-48 2016-03-08
...
1143  000791-48 2016-02-01
1144  000791-48 2016-02-02
...
1544  000986-48 2016-02-01
1545  000986-48 2016-02-02
...
1955     001617 2016-02-01
1956     001617 2016-02-02
...
2341  001768-48 2016-02-01
2342  001768-48 2016-02-02
...
2755     001937 2016-02-01
2756     001937 2016-02-02
...
lol = [pd.date_range(t.MIN_DATE, t.MAX_DATE).tolist() for t in df.itertuples()]
lns = [len(l) for l in lol]
pd.DataFrame(dict(
        PERSON_ID=df.PERSON_ID.values.repeat(lns), Date=np.concatenate(lol)
    ))[['PERSON_ID', 'Date']]

      PERSON_ID       Date
0     000099-48 2016-02-01
1     000099-48 2016-02-02
...
414      000184 2016-02-05
415      000184 2016-02-06
...
764   000461-48 2016-03-07
765   000461-48 2016-03-08
...
1143  000791-48 2016-02-01
1144  000791-48 2016-02-02
...
1544  000986-48 2016-02-01
1545  000986-48 2016-02-02
...
1955     001617 2016-02-01
1956     001617 2016-02-02
...
2341  001768-48 2016-02-01
2342  001768-48 2016-02-02
...
2755     001937 2016-02-01
2756     001937 2016-02-02
...
可以使用重塑形状,然后执行和:

结果输出:

           DATE  PERSON_ID
0    2016-02-01  000099-48
1    2016-02-02  000099-48
2    2016-02-03  000099-48
3    2016-02-04  000099-48
...         ...        ...
3976 2017-03-14  002481-48
3977 2017-03-15  002481-48
3978 2017-03-16  002481-48
3979 2017-03-17  002481-48

您也可以继续之前已经做过的工作,但可以将datetimeindex转换为字符串,然后使用
str.split
创建新行

例如:

df = df.groupby('PERSON_ID').apply(lambda x: pd.date_range(x['MIN_DATE'].values[0], x['MAX_DATE'].values[0])).reset_index()
df_dates = df.rename(columns={0: 'Dates'})
创建要转换为字符串的函数

def get_date_string(x):
     return ", ".join([d.strftime('%Y-%m-%d') for d in x])

df_dates['Dates'] = df_dates['Dates'].apply(get_date_string)
将字符串拆分为新行

s = df_dates['Dates'].str.split(", ").apply(pd.Series, 1).stack()
s.index = s.index.droplevel(-1)
s.name = 'Dates'
加入PERSON_ID列

del df[0]
print(df.join(s))

看起来无法直接在DataFrame上调用最新的melt函数,但需要将DataFrame作为参数传递给它。因此,我将其修改为'df=pd.melt(df_-dates,id_-vars=['PERSON_-id'],value_-vars=['MIN_-DATE','MAX_-DATE'],value_-name='DATE')。看起来,
melt
是在0.20.0版中作为数据帧方法引入的。如您所述,较旧版本的pandas需要pd.melt。