python - 在 Python 3.x 中使用 Pandas 根据列条件和特定列的值合并两个 DataFrame
问题描述
参考我几天前提出的问题,我现在的数据还有一个问题。我有以下两个数据框:
>>> df1
A B date
0 1 1 2015-02
1 1 1 2015-03
2 2 2 2017-01
3 2 2 2017-02
>>> df2
A B C 02-2015 03-2015 01-2017 02-2017
0 1 1 2013-07-01 0.10 0.22 0.55 0.77
1 1 1 2015-01-01 0.20 0.12 0.99 0.125
2 2 2 2016-12-01 0.13 0.15 0.15 0.245
3 2 2 2016-01-01 0.33 0.1 0.888 0.64
我想要的是跟随DataFrame:
>>> df1
A B date value
0 1 1 2015-02 0.20
1 1 1 2015-03 0.12
2 2 2 2017-01 0.15
3 2 2 2017-02 0.245
我当前的代码如下所示:
df1['value'] = df2.set_index('A', 'B').lookup(
df1.set_index('A', 'B').index, df1['date'])
这不起作用,我的 df1 是 NoneType 因为在 df2 中是条件 A 和 B == 1 的重复行。我想要的是一个附加条件,它首先提取每个 unqiue A 和 B 的最早日期,这将是A 和 B == 1 日期为 2015-02。
从 df2 开始,它应该取第 1 行,因为月份中的增量仅为 1,而不是第 0 行,增量为 18。
提前谢谢了!
解决方案
可以通过melt, lambda, sort_values, drop_dulicates
如下方式实现
df3 = df2.melt(id_vars = ['A', 'B', 'C'], var_name='date')
df3[['A', 'B']] = df3[['A', 'B']].astype(float)
df3['Diff'] = df3.apply(lambda row: abs(datetime.strptime(row['date'], '%Y-%m') - datetime.strptime(row['C'], '%Y-%m-%d')), axis=1)
df3.sort_values(['Diff'], ascending=[True], inplace=True)
df3.drop_duplicates(subset=['A', 'B', 'date'], keep='first', inplace=True)
df3.drop(['C', 'Diff'], 1, inplace=True)
df4 = df1.merge(df3, on=['A', 'B', 'date'], how='left')
输出是
A B date value
0 1.0 1.0 2015-02 0.200
1 1.0 1.0 2015-03 0.120
2 2.0 2.0 2017-01 0.150
3 2.0 2.0 2017-02 0.245
完整的例子如下。
import pandas as pd
from datetime import datetime
df1 = pd.DataFrame(columns = ['A', 'B', 'date'])
df1.loc[len(df1)] = [1, 1, '2015-02']
df1.loc[len(df1)] = [1, 1, '2015-03']
df1.loc[len(df1)] = [2, 2, '2017-01']
df1.loc[len(df1)] = [2, 2, '2017-02']
df1[['A', 'B']] = df1[['A', 'B']].astype(float)
df2 = pd.DataFrame(columns = ['A', 'B', 'C', '2015-02', '2015-03', '2017-01', '2017-02'])
df2.loc[len(df2)] = [1, 1, '2013-07-01', 0.10, 0.22, 0.55, 0.77]
df2.loc[len(df2)] = [1, 1, '2015-01-01', 0.20, 0.12, 0.99, 0.125]
df2.loc[len(df2)] = [2, 2, '2016-12-01', 0.13, 0.15, 0.15, 0.245]
df2.loc[len(df2)] = [2, 2, '2016-01-01', 0.33, 0.1, 0.888, 0.64]
df3 = df2.melt(id_vars = ['A', 'B', 'C'], var_name='date')
df3[['A', 'B']] = df3[['A', 'B']].astype(float)
df3['Diff'] = df3.apply(lambda row: abs(datetime.strptime(row['date'], '%Y-%m') - datetime.strptime(row['C'], '%Y-%m-%d')), axis=1)
df3.sort_values(['Diff'], ascending=[True], inplace=True)
df3.drop_duplicates(subset=['A', 'B', 'date'], keep='first', inplace=True)
df3.drop(['C', 'Diff'], 1, inplace=True)
df4 = df1.merge(df3, on=['A', 'B', 'date'], how='left')
print(df4)
推荐阅读
- ruby-on-rails - NoMethodError: nil:NilClass 的未定义方法“created_at”
- spring-integration - 用于过滤的 JdbcMetadataStore
- django - How to handle both save and save-as button with django class-based view
- ruby-on-rails - Browsermob 代理 + Selenium + Ruby 设置给出 550 响应
- kubernetes - 从其他 pod 连接到 MySQL pod 时崩溃(minikube 问题)
- asp.net-mvc - Azure SignalR 服务连接未激活
- assembly - 错误:x86 中“jmp”的指令后缀无效
- c - 函数指针
- javascript - 为什么获取缓存模式和标头选项无法获得新的响应?
- xslt - XSLT 1.0,复制除某些之外的所有子节点