【问题标题】:Conditional concatenation of python pandas dataframe (sql join on self)python pandas数据帧的条件连接(sql join on self)
【发布时间】:2015-07-13 17:07:31
【问题描述】:

[瞄准]
我们有一个现有的数据框,并希望在一个命令或另一个数据框中给定条件下提取一系列记录和连接(sql join on self)。

[情况]
Python版本:3.3.3
熊猫版本:0.15.1

我们有一个包含 10,000 多行的相当大的 DataFrame。这只是一个理解逻辑的例子。

DataFrame1 -> df1:

import pandas as pd
df1 = pd.DataFrame({'A': [1,2,3,1],
                    'B': [1,4,1,2],
                    'C': ['test1','test2','test3','test4']
                    })

Resulting in:
    A  B      C
    1  1  test1
    2  4  test2
    3  1  test3
    1  2  test4
    5  8  test5

[预期输出]
我们正在寻找输出:

  • 所有列 A、B、C,其中:B = 1 -> 输出 = df1[df1['B'] == 1]
  • 添加到输出所有那些

    output['A'] == df1['A']
    AND
    df1['B'] == 2

因此:

A  B      C
1  1  test1
3  1  test3
1  2  test4

展示最pythonic / pandanic(听起来很奇怪)的方式会很棒:)

【问题讨论】:

  • 您尝试过什么吗?
  • 是的,我们可以从两者中检索数据,然后将它们连接起来:out1 = df1[df1['B'] == 1] out2 = df1[df1['B'] == 2]但也许我应该指定我有一个 10,000 行以上的相当大的 DataFrame。我的意思是从技术上讲我们可以做一个 for 循环,但我确信有一种更简洁的方法可以使用一些很酷的 DataFrame 功能(concat/merge/join -> 我只是看不到条件连接)。通常我会在给定条件的情况下加入一个 SQL 表,但由于某种原因我在这种情况下看不到它
  • 鉴于上面的 out1 和 out2,我们可以做这样的事情: result = pd.merge(out1, out2, left_on='A', right_on='A', how='left') 但是在这里,我们合并了列。我想做一个 result = pd.concat(out1, out2, left_on='A', right_on='A', how='left') 但这显然会导致错误..
  • @Mark 我刚刚修改了我的答案。让我知道这是否适合你。
  • @JianxunLi 我也评论了你的回答:)。是的,它似乎有效,但我似乎无法理解为什么我们有所有这些漂亮的功能来合并列而不是行:/

标签: python python-3.x pandas


【解决方案1】:

不确定是否有更好的方法,但以下方法有效。这个想法是为您的第二个条件使用.isin 运算符。最终的布尔选择器是or 第一个条件和第二个条件的组合。

import pandas as pd
import numpy as np

# your data
# =============================
df1 = pd.DataFrame({'A': [1,2,3,1],
                    'B': [1,4,1,2],
                    'C': ['test1','test2','test3','test4']
                    })
print(df1)


   A  B      C
0  1  1  test1
1  2  4  test2
2  3  1  test3
3  1  2  test4

# processing
# =====================================
mask = df1.B == 1

df1[mask | ((df1.A.isin(df1[mask].A)) & (df1.B==2))]


   A  B      C
0  1  1  test1
2  3  1  test3
3  1  2  test4

【讨论】:

  • 是的,这可能有效,但我觉得有点奇怪,我们没有条件连接、附加或类似于合并功能的东西,但随后用于附加行:像这样(将返回c) 的严重错误:pd.concat(out1, out2, left_on='A', right_on='A', how='left')
  • @Mark 看看[] 里面的那个布尔选择器,第一部分mask 指的是第一个条件,第二部分.isin 告诉我们对于特定的行A 是否在之前的掩码和df1.B==2同时实现。我这样写是因为你要求一个“流行”的解决方案......
  • 是的,它有效:)。但是对于“pandanic”,我的意思是像合并函数一样漂亮和优雅,但不是在行上合并,而是合并列。之后,我会说我们 concat 但我在 concat 函数中没有合并功能:(
【解决方案2】:

首先

df['A'] == output['A']

将失败,除非因为长度不匹配,除非 B 中的所有值都是 1。另一方面,

df['A'][df.B == 1] == output['A']

保证都是True,就等于说x == x。这是完全多余的。在这里你需要做的就是

df[(df.B.isin([1, 2])]

【讨论】:

  • 是的,当我们在集合中寻找任何值为 1,2 的值时有效。但是,我们正在寻找所有记录 B = 1 和 B = 2,其中 A = A。在我们的集合中,有时我们可能会有这样的情况:B = 2 但没有 B = 1。因此我们想要排除这些。因此 isin() 似乎不适用?
  • 就像一个流。首先我们找到所有 B = 1 的 A,B 然后我们找到所有 B = 2 并与 A 匹配的地方。
  • 是一样的。单个记录不能满足 B = 1 和 B = 2,它必须是其中之一。 A = A 是一个重言式,即它始终为真。除非您想对仅满足 B == 1 的子集进行某些操作,否则无需分两步完成。问题就像获取 B 为 1 或 2 的所有行一样简单,除非我遗漏了什么,但从你的例子来看,这就是它的样子。
  • 我很抱歉造成混乱。我们的集合有时可以包含例如 A=10,B=2,但没有 A=10,B=1。由于 B=1 不在我们想要排除的集合中。
  • 所以你的意思是,如果有两行 A 等于某个值,一个 B = 1,一个 B = 2,那么你只包含 A 等于某个值的行?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-04-07
  • 1970-01-01
  • 2019-03-14
  • 1970-01-01
  • 1970-01-01
  • 2020-09-02
  • 2019-07-03
相关资源
最近更新 更多