2017-02-14 77 views
1

我目前工作的一個CSV數據集看起來像下面(參見下面的測試DF):如何根據熊貓中的多個條件來匹配和計算行數?

enter image description here

這些基本上是移動設備的位置的記錄。 「標識符」唯一標識移動設備,「from_city」和「to_city」是相應的出發和到達城市。因此,對於標識符「A1」,該人在1月2日離開渥太華前往倫敦(記錄編號2),並在1月3日返回(記錄編號5)。而對於標識符爲A2,B1,B2,B3和B6的記錄,由於沒有倫敦到渥太華的記錄,它們將被視爲無回報。

最終,我想要做的是找出所有出發和返回的匹配項,並計算它們對於每個從到城市對。例如:

從渥太華到倫敦:共100次旅行,3天內返回80天,3天后返回10天,10次未返回。

我想我需要在使用標識符和其他列的熊貓中做groupby。但問題是我如何識別標識符組中的返回匹配?

從本質上講,標準應該是:

  • 相同標識符
  • FROM_CITY和TO_CITY在兩個記錄之間逆轉
  • 返回時間應該是晚於發車時間

加,我如何嵌入3天內的標準?

在此先感謝您的幫助!

下面是測試數據幀:

df = pd.DataFrame({ 
    'Identifier': ['A1', 'A2', 'A3', 'A1', 'A3', 'B1', 'C3', 'B2', 'B3', 'B6', 'C3'], 
    'OS': ['iphone', 'iphone', 'iphone', 'iphone', 'iphone', 'iphone', 'iphone', 'iphone', 'iphone', 'iphone', 'iphone'], 
    'from_city': ['ottawa', 'ottawa', 'ottawa', 'london', 'london', 'ottawa', 'ottawa', 'ottawa', 'ottawa', 'ottawa', 'london'], 
    'to_city': ['london', 'london', 'london', 'ottawa', 'ottawa', 'london', 'london', 'london', 'london', 'london', 'ottawa'], 
    'time': ['1/2/2017 21:00', '1/2/2017 20:00', '12/24/2016 13:00', '1/3/2017 21:00', '1/6/2017 0:00', 
      '12/10/2016 17:00', '12/22/2016 21:00', '12/17/2016 23:00', '12/14/2016 19:00', '12/20/2016 18:00', '1/3/2017 0:00'] 
}) 

注:在上述IMG 5日線的日期應爲「2017年1月3日」,這是上面的固定代碼。

回答

1

我終於想出了一個辦法做到這一點:

def combine_cities(row): 
    if row['from_city'] < row['to_city']: 
     return row['from_city'] + ', ' + row['to_city'] 
    else: 
     return row['to_city'] + ', ' + row['from_city'] 

df['cities'] = df.apply(combine_cities, axis=1) 

def count_return(grp): 
    if grp.nunique() == 1: 
     return np.nan 
    else: 
     return 'return found' 

df.groupby(['cities', 'Identifier'])['from_city'].apply(count_return).dropna() 
1

如果每個標識符在您的數據集中只有一次往返,此方法可能有效。另外,我改變了time列第4單元的一年中你的樣本數據幀到2017年

首先轉換df['time']爲DateTime。

duration = df.groupby('Identifier')['time'].apply(lambda x: max(list(x)) - min(list(x)))

然後用GROUPBY上Identifier,:

duration = df.groupby('Identifier')['time'].apply(lambda x: max(list(x)) - min(list(x)))

duration現在看起來像: A1 1 days 00:00:00 A2 0 days 00:00:00 A3 12 days 11:00:00 B1 0 days 00:00:00 B2 0 days 00:00:00 B3 0 days 00:00:00 B6 0 days 00:00:00 C3 11 days 03:00:00

現在選擇是大於0天行,但不比3天。

duration[(duration > pd.Timedelta(days=0)) & (duration <= pd.Timedelta(days=3))]

導致: Identifier A1 1 days Name: time, dtype: timedelta64[ns]

+0

謝謝你@ user666!我會嘗試它,並根據需要upvote和/或標記。 –

+0

看起來你的回答沒有考慮到回報因素 - 城市對需要扭轉,如果第一條記錄是「渥太華倫敦」,那麼基本上回報記錄應該有「倫敦渥太華」。 –

+0

有意義,但是您的數據集沒有這種情況。你能更新你的描述還是示例數據框? – user666

2
# change the type of 'time' column to timestamp 

df['timestamp']=pd.to_datetime(df['timestamp'], format='%m/%d/%Y %H:%M') 

# first use merge to get leave time and back time 

df = df.merge(df.set_index(['Identifier','from_city'])[['timestamp']], how='left', left_on=['Identifier','to_city'], right_index=True, suffixes=['_leave','_back']) 

# filter out invalid leave date and back date 

df = df.loc[~(df['timestamp_leave']>=df['timestamp_back'])] 

# calculate travel time 

df['duration'] = (df['timestamp_back'] - df['timestamp_leave']).dt.days 

use pd.cut to groupby 

df['group'] = pd.cut(df['duration'], [0,3,10,100]) 

返回值:

Identifier OS from_city timestamp_leave to_city timestamp_back duration group 
1 A2 iphone ottawa 2017-01-02 20:00:00 london NaT NaN NaN 
2 A3 iphone ottawa 2016-12-24 13:00:00 london 2017-01-06 00:00:00 12.0 (10, 100] 
3 A1 iphone london 2016-01-03 21:00:00 ottawa 2017-01-02 21:00:00 365.0 NaN 
5 B1 iphone ottawa 2016-12-10 17:00:00 london NaT NaN NaN 
6 C3 iphone ottawa 2016-12-22 21:00:00 london 2017-01-03 00:00:00 11.0 (10, 100] 
7 B2 iphone ottawa 2016-12-17 23:00:00 london NaT NaN NaN 
8 B3 iphone ottawa 2016-12-14 19:00:00 london NaT NaN NaN 
9 B6 iphone ottawa 2016-12-20 18:00:00 london NaT NaN NaN 
+0

謝謝@ heyu91!我會嘗試它,並根據需要upvote和/或標記。 –

+0

我得到了一個錯誤,運行你的代碼......「TypeError:不支持的操作數類型爲 - :'str'和'str'」。你能給我一些進一步的指導嗎? –

+0

我認爲這是'時間'欄的類型。也許你的'時間'類型是字符串。嘗試在代碼開始處添加'df ['time'] = pd.to_datetime(df ['time'],format ='%m /%d /%Y%H:%M')'。 – heyu91