【问题标题】:How to return unique pairs from a dataframe based on another column's values?如何根据另一列的值从数据框中返回唯一对?
【发布时间】:2017-02-02 18:21:32
【问题描述】:

我有一个如下所示的数据框:

Date        A   B   Number
2017-01-01  a   b   0.9240
2017-01-01  b   c   0.9101
2017-01-01  d   e   0.8761
2017-01-01  c   g   0.9762
2017-01-02  b   c   0.5637
2017-01-02  c   d   0.9643

我希望每天在 A 和 B 中都有一个唯一值的数据框,具体取决于数字列中的数字。我认为逻辑将按以下顺序排列:

  1. 按日期对数据框进行分组
  2. 将 A 列中的每个值与 B 列中的每个值进行比较,以检查是否存在类似的值。
  3. 对于所有匹配值,比较 Number 列并找出两个值中的最大值。
  4. 返回具有唯一值的新数据框。

例如,从上面的数据框中,因为 2017 年 1 月 1 日 A 列和 B 列中有一个“b”,我想比较 0.9240 和 0.9101 并返回 0.9240 的行,因为它高于 0.9101 .

最终产品应如下所示:

Date        A   B   Number
2017-01-01  a   b   0.9240
2017-01-01  d   e   0.8761
2017-01-01  c   g   0.9762
2017-01-02  c   d   0.9643

【问题讨论】:

  • 这并不能解释为什么 2017-01-01 d e 0.8761 保留为 d 和 e 在 1 月 1 日是唯一的。

标签: python pandas group-by compare unique


【解决方案1】:

这很复杂,但绝对有可能。

首先让我们确保数据格式正确:

df.info()

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 6 entries, 0 to 5
Data columns (total 4 columns):
Date      6 non-null datetime64[ns]
A         6 non-null object
B         6 non-null object
Number    6 non-null float64
dtypes: datetime64[ns](1), float64(1), object(2)
memory usage: 272.0+ bytes

请注意,Date 列的类型为 datetime64。这是必要的,因为将这些值作为时间戳允许使用 pandas resample 方法每天对数据进行分组。

重新采样数据后,可以应用自定义方法extract。此方法将一组作为数据框并应用逻辑。通过使用 pandas pivot_table 方法,可以更轻松地找到 A 列和 B 列之间的交集。我不确定这是否是最有效的方法,但如果数据集不是太大,它应该可以足够快地工作。

完整的代码如下所示:

def extract(df):
    dfs = []
    pt = df.reset_index().pivot_table('Number', columns=['A', 'B'], index='Date')

    # find any intersection of values between col A and B
    intersection = set(pt.columns.levels[0].values)\
        .intersection(set(pt.columns.levels[1].values))
    # iterate over all intersections to compare their values 
    # and choose the largest one
    for value in intersection:
        mask = (df['A'] == value) | (df['B'] == value)
        df_intersection = df[mask]\
            .sort_values('Number', ascending=False)
        dfs.append(df_intersection.ix[[0]])

    # find all rows that do not contain any intersections
    df_rest = df[(~df['A'].isin(list(intersection))) &\
                 (~df['B'].isin(list(intersection)))]
    if (len(df_rest) > 0):
        dfs.append(df_rest)

    return pd.concat(dfs)

df.set_index('Date')\
    .resample('d')\
    .apply(extract)\
    .reset_index(level=1, drop=True)

这段代码导致:

            A  B  Number
Date                    
2017-01-01  a  b  0.9240
2017-01-01  c  g  0.9762
2017-01-01  d  e  0.8761
2017-01-02  c  d  0.9643

上面的代码基于给定的数据集:

import pandas as pd
from io import StringIO

data = StringIO("""\
Date        A   B   Number
2017-01-01  a   b   0.9240
2017-01-01  b   c   0.9101
2017-01-01  d   e   0.8761
2017-01-01  c   g   0.9762
2017-01-02  b   c   0.5637
2017-01-02  c   d   0.9643
""")
df = pd.read_csv(data, sep='\s+', parse_dates=[0])

【讨论】:

    猜你喜欢
    • 2016-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-16
    • 2022-12-06
    • 2020-09-28
    • 1970-01-01
    相关资源
    最近更新 更多