pandas Dataframe,根据其他行的选择分配值

时间:2016-11-28 16:07:57

标签: python-3.x pandas dataframe

我在python 3中有一个pandas DataFrame。

在这个DataFrame中,有两列中具有相同值的行(这可以是整个部分),我将其称为一个组。 每行在列中也有True / False值。

现在,我想知道每一行其组中的任何行是否具有False值,如果是,我想为False赋值import pandas as pd import numpy as np df = pd.DataFrame({'E': [np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan], 'D': [0, 1, 2, 3, 4, 5, 6], 'C': [True, True, False, False, True, True, True], 'B': ['aa', 'aa', 'aa', 'bb', 'cc', 'dd', 'dd'], 'A': [0, 0, 0, 0, 1, 1, 1]}) 另一列中该组中的每一行。我已经设法在for循环中执行此操作,但它很慢:

df:
     A   B      C  D    E
  0  0  aa   True  0  NaN
  1  0  aa   True  1  NaN
  2  0  aa  False  2  NaN
  3  0  bb  False  3  NaN
  4  1  cc   True  4  NaN
  5  1  dd   True  5  NaN
  6  1  dd   True  6  NaN

给出了:

for i in df.index:
    df.ix[i, 'E'] = df[(df['A'] == df.iloc[i]['A']) & (df['B'] == df.iloc[i]['B'])]['C'].all()

现在我运行for循环:

df:
     A   B      C  D      E
  0  0  aa   True  0  False
  1  0  aa   True  1  False
  2  0  aa  False  2  False
  3  0  bb  False  3  False
  4  1  cc   True  4   True
  5  1  dd   True  5   True
  6  1  dd   True  6   True

然后给出所需的结果:

.apply()

当我的整个DataFrame运行大约100万行时,这需要很长时间。因此,考虑使用def f(x): return False not in x df.groupby(['A','B']).C.apply(f) 来避免for循环,我偶然发现了以下问题:apply a function to a pandas Dataframe whose retuned value is based on other rows

但是:

A  B 
0  aa    False
   bb     True
1  cc     True
   dd     True

返回:

<input type="file" id="appbundle_evento_brochure_upload" name="img_uploader_brochure" class="image_upload">

有没有人知道更好的方法或如何解决最后一种情况?

1 个答案:

答案 0 :(得分:1)

您可以尝试使用pd.merge进行SQL样式的连接。

执行您正在执行的相同groupby,但对其应用min()以查找C == True的任何案例。然后将其转换为DataFrame,将列重命名为“E”,并将其合并回df。

df = pd.DataFrame({'D': [0, 1, 2, 3, 4, 5, 6],
               'C': [True, True, False, False, True, True, True],
               'B': ['aa', 'aa', 'aa', 'bb', 'cc', 'dd', 'dd'],
               'A': [0, 0, 0, 0, 1, 1, 1]})

falses = pd.DataFrame(df.groupby(['A', 'B']).C.min() == True)
falses = falses.rename(columns={'C': 'E'})

df = df.merge(falses, left_on=['A', 'B'], right_index=True)