【问题标题】:Pandas reshaping date frame, groupby bins熊猫重塑日期框架,groupby bins
【发布时间】:2016-03-21 03:06:57
【问题描述】:

在重塑熊猫数据框方面,我需要您的帮助。我对 pandas 很陌生(虽然已经恋爱了),但这个问题一直困扰着我。

我从事一项环境研究,其中包括计算特定路线上的汽车数量,记录它们的出发地和目的地以及乘客人数。

数据框看起来像这样(实际上它包含 10,000 行除外)

df = pd.DataFrame(
    {'date':['20151201','20151202','20151203','20151204','20151204','20151205','20151206','20151207','20151210','20151211','20151212','20151225'],
                   'id':[123,234,543,890,543,123,234,543,123,123,123,890],
                   'event':[1,1,1,1,-1,-1,-1,-1,-1,-1,-1,-1],
                   'city':['AB','YU','CD','CD','YU','YU','BA','AB','CB','BA','CY','CC'],
                   'number of passengers':[1,5,1,20,1,1,5,10,2,25,3,20]
    }
)

   city      date  event   id  number of passengers
0    AB  20151201      1  123                     1
1    YU  20151202      1  234                     5
2    CD  20151203      1  543                     1
3    CD  20151204      1  890                    20
4    YU  20151204     -1  543                     1
5    YU  20151205     -1  123                     1
6    BA  20151206     -1  234                     5
7    AB  20151207     -1  543                    10
8    CB  20151210     -1  123                     2
9    BA  20151211     -1  123                    25
10   CY  20151212     -1  123                     3
11   CC  20151225     -1  890                    20

其中 df['event'] 表示城市是汽车的起点 (1) 还是目的地 (-1) 。 df['id'] 是汽车的唯一标识符(车牌)。

为了让事情变得更加复杂(至少对我而言),可以对返回同一路线、同一天或另一天的汽车进行多次观察,当然观察结果是不完整的(例如,汽车返回原点未被注意到)。

df.set_index(['id','date','event']).unstack('event').swaplevel(0,1,axis=1)


event          -1    1                   -1                    1
             city city number of passengers number of passengers
id  date                                                        
123 20151201  NaN   AB                  NaN                    1
    20151205   YU  NaN                    1                  NaN
    20151210   CB  NaN                    2                  NaN
    20151211   BA  NaN                   25                  NaN
    20151212   CY  NaN                    3                  NaN
234 20151202  NaN   YU                  NaN                    5
    20151206   BA  NaN                    5                  NaN
543 20151203  NaN   CD                  NaN                    1
    20151204   YU  NaN                    1                  NaN
    20151207   AB  NaN                   10                  NaN
890 20151204  NaN   CD                  NaN                   20
    20151225   CC  NaN                   20                  NaN

我的目标是创建一个数据框,显示来自一个城市的所有交通、目的地以及乘客数量的观察结果(理想情况下分为诸如'(1-2)、( 3-5), (6-7), (>7))

理想情况下,我希望生成的数据框看起来像这样:

Origin Destination     0-2     3-5     6-7   >7
AB    YU                1       0      0     0
      CB                1       0      0     0
      BA                0       0      0     1
      CY                0       1      0     0
YU    BA                0       2      0     0
CD    YU                1       2      0     0
      AB                0       0      1     0
      CC                0       0      0     1

我已经通过

添加了一个起点和终点列
df['origin']= np.where(df['event'] == 1,df['city'],np.NAN)
df['destination']= np.where(df['event'] == -1,df['city'],np.NAN)

但接下来的重塑步骤让我望而却步。我用 pandas pivot 和 pandas unstack 尝试了一些东西,但似乎我遗漏了一些东西,因为它们都不起作用。我想我还需要在某个时间点使用 pandas cut 进行分箱,但我的分析未能达到这一阶段。

你能指出我正确的方向吗?我将如何重塑数据以实现按来源查看流量?

【问题讨论】:

  • 您的输出与您的输入不匹配。请提供一个可重现的例子。
  • 道歉并感谢您指出这一点,博维尔上校。我已经编辑了这个问题以提供一个更清晰(我希望)的例子。再次感谢。

标签: python pandas dataframe reshape


【解决方案1】:

向您致以最诚挚的歉意,因为这很难遵循,所以如果有人能想到更简单的方法,那就去吧,但是你去:

df['number of passengers'] = pd.cut(df['number of passengers'], 
                                bins=[0, 2, 5, 7, max(df['number of passengers']) + 1], 
                                right=False)

# Recode the factor levels for readable column labels when unstacked
df.ix[df['event']==1, 'event'] = 'origin'
df.ix[df['event']==-1, 'event'] = 'destination'

# Split the DataFrame, unstack each factor, then join
new_df = pd.DataFrame(
    df.groupby('id')['number of passengers'].value_counts()
).unstack(
    'number of passengers'
).fillna(0).join(
    df.set_index('id')[['city', 'date', 'event']].reset_index().set_index(
        ['id', 'date', 'event']
    ).unstack('event').reset_index(level='date', drop=True)
).reset_index()

# Flatten the column multiindex
new_df.columns = new_df.columns.droplevel()
new_df.columns = ['id', '[0, 2)', '[2, 5)', '[5, 7)', '> 7', 'destination', 'origin']

# If we don't do this, there will be separate rows for origins and destinations
new_df['origin'] = new_df['origin'].fillna(method='ffill')
new_df = new_df.dropna().set_index(['id', 'origin', 'destination'], drop=True)

new_df = new_df.reset_index()[['origin', 'destination', '[0, 2)', '[2, 5)', '[5, 7)', '> 7']].set_index(['origin', 'destination'])
new_df

给你这个:

                    [0, 2)  [2, 5)  [5, 7)  > 7
origin  destination             
AB      YU          2       2       0       1
        CB          2       2       0       1
        BA          2       2       0       1
        CY          2       2       0       1
YU      BA          0       0       2       0
CD      YU          2       0       0       1
        AB          2       0       0       1
        CC          0       0       0       2

【讨论】:

  • 感谢亚当的回答。但是,在跟进您的代码时,在运行 new_df = pd.DataFrame(...) 行时出现错误“未找到乘客级别数”。知道为什么吗?非常感谢!
  • 不。在这里仍然可以正常工作。也许您正在使用未实现这些方法之一的旧熊猫版本?我正在使用 0.17.0。
猜你喜欢
  • 1970-01-01
  • 2017-08-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多