2017-07-06 7 views
2

私には2つのデータフレームがあり、1つは購買データ、もう1つは週単位のカレンダーです。 DF1の「purchased_at」日付「はweek_start」と「week_end」の間に収まる場所に基づいてDF2から選択され、私はDF1に「week_no」列を追加するために、2つのデータを使用したいPythonは複雑な基準に基づいて2番目のデータフレームから行を選択します

df1: 
purchased_at product_id cost 
01-01-2017 1   £10 
01-01-2017 2   £8 
09-01-2017 1   £10 
18-01-2017 3   £12 

df2: 
week_no week_start week_end 
1  31-12-2016 06-01-2017 
2  07-01-2017 13-01-2017 
3  14-01-2017 20-01-2017 

、 DF2の日付、すなわち

df1: 
purchased_at product_id cost week_no 
01-01-2017 1   £10 1 
01-01-2017 2   £8 1 
09-01-2017 1   £10 2 
18-01-2017 3   £12 3 

私が検索したが、私は、データが2間の比較を用いて第2のデータフレームから引き出されている、と私はすることはできませんされてきた例を見つけることができるされていませんでした私が見つけた例を正しく適用してください。

df1.loc[(df1['purchased_at'] < df2['week_end']) & 
     (df1['purchased_at'] > df2['week_start']), df2['week_no'] 

はValueErrorをして、失敗したことは誰もがこの問題に役立つ、または達成するためのより良い方法があるかどうか、私は提案を開いてるでし

「は同一の標識Seriesオブジェクトを比較することができます」を同じ結果。

DF1全データフレームヘッダを

purchased_at purchase_id product_id product_name transaction_id account_number cost 
01-01-2017 1   1   A    1    AA001   £10 
01-01-2017 2   2   B    1    AA001   £8 
02-01-2017 3   1   A    2    AA008   £10 
03-01-2017 4   3   C    3    AB040   £12 
... 
09-01-2017 12   1   A    10    AB102   £10 
09-01-2017 13   2   B    11    AB102   £8 
... 
18-01-2017 20   3   C    15    AA001   £12 

増分各行でそうpurchase_id増加をDF1のさらなる詳細を追加する

編集、PRODUCT_IDとPRODUCT_NAME 1持っている:1の関係をtransaction_idも段階的に増加しますが、トランザクション内で複数の購入が可能です。

+0

'df1'の日付を解析すると、あなたが使用している定義が*標準*のように見えるので十分です。では、代わりに[this](https://stackoverflow.com/questions/2600775/how-to-get-week-number-in-python)を見て、その時点で 'df2'を忘れてしまいます。 –

+0

クエリでは、データフレームは(一般的に)全く異なる形をしています。それぞれのデータフレームにあなたが参加できる鍵(https://pandas.pydata.org/pandas-docs/stable/merging.html)を構築する必要があります(df1の曜日を開始してください)。上のコメントとともに、これは解決策を示唆するはずです – Quickbeam2k1

+0

カウントは今後の年に続きますので、来年は53-104週間などとなりますので、私はそれに参加したいと思っています組み込み式から計算するのではなく、別々に – Sarah

答えて

0

データフレームが大きい場合は、このトリックを使用できます。

フルcartisian製品はすべてのレコードにすべてのレコードの結合を実行します。

df_out = pd.merge(df1.assign(key=1),df2.assign(key=1),on='key') 

次は、この場合には条件に一致しないそれらのレコードを除外し、purchased_atはweek_startの間ではなく、

(df_out.query('week_start < purchased_at < week_end') 
     .drop(['key','week_start','week_end'], axis=1)) 
をweek_end場所

出力:

purchased_at product_id cost week_no 
0 2017-01-01   1 £10  1 
3 2017-01-01   2 £8  1 
7 2017-01-09   1 £10  2 
11 2017-01-18   3 £12  3 

大きなデータフレームがある場合は、numpy methodをPiRSquaredの提案に従って使用できます。

a = df1.purchased_at.values 

bh = df2.week_end.values 

bl = df2.week_start.values 

i, j = np.where((a[:, None] >= bl) & (a[:, None] <= bh)) 

pd.DataFrame(
    np.column_stack([df1.values[i], df2.values[j]]), 
    columns=df1.columns.append(df2.columns) 
).drop(['week_start','week_end'],axis=1) 

出力:

  purchased_at product_id cost week_no 
0 2017-01-01 00:00:00   1 £10  1 
1 2017-01-01 00:00:00   2 £8  1 
2 2017-01-09 00:00:00   1 £10  2 
3 2017-01-18 00:00:00   3 £12  3 
+0

numpyメソッドは本当に便利ですが、 'weeks_no'の出力は '購入日'の日付ごとに複製されます。つまり、上記の出力の代わりに16行あります。 purchased_at product_id ... week_no 2017-01 2017年1月1日1〜3 2017年1月1日2 1 2017年1月1日2 1 -01 1 1 2017年1月1日1 1 2017年1月1日1 2 ... マイコードがあなたの例に合っているように見えますが、どこが間違っているのか考えていますか? – Sarah

+0

謝罪、それははっきりと出てこない。要約すると、 'purchased_at'、 'product_id'、 'cost'の各行はそれぞれ4回複製され、week_noの出力は[1,1,2,3,1,1,2,3,1,1,2,2、 3,1,1,2,3] – Sarah

+0

Sarah ...あなたは私にデータと問題解決のための期待される出力を与えなければならないでしょう。私の唯一の推測は、おそらく、私たちが参加してcartisan製品を作成しており、コードにproduct_idのような追加の制約が必要であるということです。 –

0

あなただけの日から週番号を抽出するためにtime.strftime()を使用することができます。あなたが上向きに週を数えておきたい場合は、あなたは、時系列のスタートとして「ゼロ年」を定義し、それに応じてweek_noを相殺する必要があります。ここでは

import pandas as pd 

data = {'purchased_at': ['01-01-2017', '01-01-2017', '09-01-2017', '18-01-2017'], 'product_id': [1,2,1,3], 'cost':['£10', '£8', '£10', '£12']} 

df = pd.DataFrame(data, columns=['purchased_at', 'product_id', 'cost']) 

def getWeekNo(date, year0): 
    datetime = pd.to_datetime(date, dayfirst=True) 
    year = int(datetime.strftime('%Y')) 
    weekNo = int(datetime.strftime('%U')) 
    return weekNo + 52*(year-year0) 

df['week_no'] = df.purchased_at.apply(lambda x: getWeekNo(x, 2017)) 

、私はから日付ストリングを変換するpd.to_dateime()を使用dfをdatetime-objectに変換します。 strftime('%Y')は、年を返し、strftime('%U')を返します(年の最初の週が最初の日曜日から始まります)。週が月曜日に始まる場合は、代わりに'%W'を使用してください)。

このように、週単位のデータフレームのみを管理する必要はありません。

関連する問題