【问题标题】:Pandas to create a conditional column by selecting multiple columns in two different dataframes/pandasPandas 通过在两个不同的数据框/熊猫中选择多个列来创建条件列
【发布时间】:2019-05-01 15:35:36
【问题描述】:

问题:我有 2 个数据框;

  1. df1 有coil_id、sample_factor、seq。每个线圈 ID 有 449 条记录(范围 1-499),并且有大约 1000 个唯一线圈 ID。
  2. df2 具有线圈 ID、样品、量规。每个线圈 ID 大约有 500 条记录(范围 10-5000;可以更少),并且具有与 df1 中相同的 1000 个唯一线圈 ID。

df1:

+-------+-----------------
|coil_id|sample_factor|SEQ
+-------+-----------------
|E101634|10.4066      |  1
|E101634|20.8132      |  2
|E101634|31.2198      |  3 
|E101634|41.6264      |  4
|E101634|5220.033     |449

df2:

+-------+------+------+--
|coil_id|SAMPLE|GAUGE |
+-------+------+------+--
|E101634|    10|0.0565|
|E101634|    20|0.0569|
|E101634|    30|0.0567|
|E101634|    40|0.0561|
|E101634|  5000| 0.055|

由于记录数不同,我无法加入两个表。如果我这样做,我的样本值和量规会发生变化。所以我不应该加入。 接下来,我需要检查 df1.sample_factor 是否位于 df2.sample 和 df2.sample+1 之间,然后对仪表进行计算。 示例:(如果 10.4 介于 10 和 20 之间,则 0.0565+((((0.0569-0.0565)/10)*(10.4-10)) )基本上按比例分配仪表。

我想从 df1 中的 Sample_factor 迭代每一行,并检查它是否位于 df2 中的 sample[i] 和 sample[i+1] 之间。然后在仪表上按比例执行并将结果添加到 df1。

我试过这个:

def new_gauge : for row in df1('sample_factor'):
    if df1['sample_factor'] > df2['sample'] and df1['sample_factor'] < df2['sample'] + 1:
        return df2['gauge']+(((df2['gauge']+1)-df2['gauge'])/10)*(df1['sample_factor']-df2['sample']))
df1['new_gauge'] = df1.apply(new_gauge)

我知道它的语法绝对错误,只是为了了解我想要什么。

感谢任何帮助。谢谢:)

输出:

【问题讨论】:

  • 我想你昨天问过这个问题。我有一个我删除的解决方案,因为我不完全确定您的预期输出。您能否将每一行的 'new_gauge' 的预期输出添加到 df1,以便我可以验证我的计算是否正确完成?
  • 感谢您的回复。我昨天还没有尝试过您的代码,今天正要尝试但它已经消失了。很高兴你回应。我添加了我期望的输出的屏幕截图。 'new_gauge' 是计算结果。
  • 但是你能帮我计算出其中的几个数字吗?您在数学中缺少 1 个右括号,因此很难知道正确的操作顺序
  • 完成!!请检查。谢谢。
  • excel公式=E2+(((E3-E2)/10)*(C3-D2))。但这只是一个计算,没有检查 Sample_factor 是否在 2 个样本之间。

标签: python pandas dataframe pyspark pyspark-sql


【解决方案1】:

这是与您的预期输出相匹配的起始样本数据

df1

   coil_id  sample_factor  SEQ
0  E101634        10.4066    1
1  E101634        20.8132    2
2  E101634        31.2198    3
3  E101634        41.6264    4
4  E101634        52.0330    5
5  E101634        62.4396    6
6  E101634      5220.0330  449

df2

   coil_id  SAMPLE   GAUGE
0  E101634      10  0.0550
1  E101634      20  0.0568
2  E101634      30  0.0543
3  E101634      40  0.0531
4  E101634      50  0.0529
5  E101634      60  0.0519

第一步是merge_asof将样本因子带到最接近的样本。然后计算每一行的new_gauge 列。但是,如果 sample_factor 位于其当前行和下一行的值之间,并且线圈 ID 与下一行相同,我们只会实际分配一个值。

import pandas as pd

merged = pd.merge_asof(df2.assign(SAMPLE = df2.SAMPLE.astype('float')).sort_values('SAMPLE'), 
                       df1.sort_values('sample_factor'),
                       by='coil_id',
                       left_on='SAMPLE',
                       right_on='sample_factor',
                       direction='forward')
print(merged)
#   coil_id  SAMPLE   GAUGE  sample_factor  SEQ
#0  E101634    10.0  0.0550        10.4066    1
#1  E101634    20.0  0.0568        20.8132    2
#2  E101634    30.0  0.0543        31.2198    3
#3  E101634    40.0  0.0531        41.6264    4
#4  E101634    50.0  0.0529        52.0330    5
#5  E101634    60.0  0.0519        62.4396    6

# Now perform your calculation:
new_gauge = (merged.GAUGE.shift(1) 
             + ((merged.GAUGE - merged.GAUGE.shift(1))/10 
                 * (merged.sample_factor - merged.SAMPLE.shift(1))))

# Assign it only where it makes sense
# Assumes df2 was sorted on ['coil_id',  'SAMPLE']
mask = (merged.sample_factor.between(merged.SAMPLE, merged.SAMPLE.shift(-1)) 
        & (merged.coil_id == merged.coil_id.shift(-1)))

merged.loc[mask, 'new_gauge'] = new_gauge[mask] 

输出:merged

   coil_id  SAMPLE   GAUGE  sample_factor  SEQ  new_gauge
0  E101634    10.0  0.0550        10.4066    1        NaN
1  E101634    20.0  0.0568        20.8132    2   0.056946
2  E101634    30.0  0.0543        31.2198    3   0.053995
3  E101634    40.0  0.0531        41.6264    4   0.052905
4  E101634    50.0  0.0529        52.0330    5   0.052859
5  E101634    60.0  0.0519        62.4396    6        NaN

在这种情况下,我们没有分配最后一行,因为您提供的子集中没有 Sample > 60。

【讨论】:

  • 非常感谢。我会试一试,然后告诉你。
  • @Abhinavneni 很高兴它有帮助! merge_asof 是使用较少的 pandas 方法之一,但它确实适合这样的计算。虽然有很多预处理才能让它工作(排序,并确保合并键是同一类型。令人震惊的是它无法合并intfloat 列。¯.
猜你喜欢
  • 2013-11-03
  • 2015-08-12
  • 2019-11-25
  • 2022-01-15
  • 1970-01-01
  • 2019-08-14
  • 2019-12-13
  • 2013-02-13
  • 1970-01-01
相关资源
最近更新 更多