如何将熊猫中的行放在一列上并满足另一列上的方程式?

时间:2019-06-19 09:50:23

标签: python pandas pandas-groupby drop-table

我正在处理一些包含冲销的财务数据。反转基本上是表中的一种校正,它通过在表中添加等量的相反符号来抵消表中的另一个值。我的工作是清除这些价值观。 以这个数据框为例:

df = pd.DataFrame({"a":["a","b","c","a","a"],
                  "b":[-2,5,2,2,7],
                 "xtra_col":["X","X","X","X","X"]})

    a   b   xtra_col
0   a   -2  X
1   b   5   X
2   c   2   X
3   a   2   X
4   a   7   X

在这种情况下,第3行与第0行相反,因此必须将其删除。同时,第2行不是第0行的反转,尽管值相反,因为它们在a列上不匹配。 结果必须如此。

    a   b   xtra_col
0   b   5   X
1   c   2   X
2   a   7   X

问题是,如何从表中删除此类冲销?我已经看过drop_duplicates()的子集为a和b,但这行不通,因为它只会匹配相同的值,而不会匹配相反的值。 我感到可以使用groupby来达成某些目标,但是我不确定如何组织它。

附加说明,它在负数为奇数的情况下也应起作用。考虑以下情况,输出应如下:

df = pd.DataFrame({"a":["a","b","c","a","a"],
                  "b":[-2,5,2,2.0,-2],
                 "xtra_col":["X","X","X","X","X"]})


a   b   xtra_col
0   a   -2.0    X
1   b   5.0 X
2   c   2.0 X
3   a   2.0 X
4   a   -2.0    X

输出应为:

a   b   xtra_col
1   b   5.0 X
2   c   2.0 X
3   1   -2.0    X

3 个答案:

答案 0 :(得分:3)

如果仅可能有一个数字列None,则创建过滤后的DataFrame,将b反转多个b,并按DataFrame.merge匹配行,最后按{{ 3}}和Series.isin

-1

如果可能的话,另外df1 = df[df['b'].lt(0)].copy() df1['b'] *= -1 df2 = df1.reset_index().merge(df.reset_index(), on=['a','b']).filter(like='index_') print (df2) index_x index_y 0 0 3 df = df[~df.index.isin(df2.values.ravel())] print (df) a b xtra_col 1 b 5 X 2 c 2 X 4 a 7 X 行,并且您需要避免将其删除(因为不与另一行a 2配对),并在过滤后的原始a -2中为计数器列添加boolean indexing:< / p>

DataFrame

答案 1 :(得分:1)

在python中使用SQL的功能。在这里,您将表(数据框)连接到其自身,同时检查列a相同而列b反转的情况。然后使用where子句进行过滤。

请参见下面的样机:

import sqlite3
import pandas as pd
import numpy as np
df = pd.DataFrame({"a":["a","b","c","a","a"],
                  "b":[-2,5,2,2,7],
                 "xtra_col":["X","X","X","X","X"]})

#Make the db in memory
conn = sqlite3.connect(':memory:')
df.to_sql('tab', conn, index=False)

qry = '''
    select  
       tab1.a,tab1.b,tab1.xtra_col
    from
        tab as tab1 

        left join tab as tab2 on
            tab1.a =tab2.a
            and
            tab1.b = -tab2.b
        where tab2.a is null
    '''
dfres = pd.read_sql_query(qry, conn)
dfres

和结果在这里:

a   b   xtra_col
0   b   5   X
1   c   2   X
2   a   7   X

答案 2 :(得分:0)

这是使用apply查找无效行并将其删除的另一种方法:

# Import module
import pandas as pd

# Your data
df = pd.DataFrame({"a": ["a", "b", "c", "a", "a"],
                   "b": [-2, 5, 2, 2, 7],
                   "xtra_col": ["X", "X", "X", "X", "X"]})

# Filtering function
def filter_row(row):
    # Your condition comparing the current row with the whole dataframe
    if sum((df.a == row.a) & (df.b == -row.b)) == 1:
        return row

# Apply the filter method
row_to_remove = df.apply(filter_row, axis=1)
print(row_to_remove)  # You can use drop NA to remove NA rows
#       a    b xtra_col
# 0     a - 2.0       X
# 1  None  NaN     None
# 2  None  NaN     None
# 3     a  2.0        X
# 4  None  NaN     None

# Drop invalid rows
result = df[(df != row_to_remove).any(axis=1)]
print(result)
#    a  b xtra_col
# 1  b  5        X
# 2  c  2        X
# 4  a  7        X