如果数据框内列表上的任何值在另一个列表中,则过滤熊猫数据框行

时间:2019-01-16 09:42:52

标签: python pandas python-2.7

我有一个pandas dataframe,其中包含split_categories列中的列表:

df.head()

      album_id categories split_categories
    0    66562    480.494       [480, 494]
    1   114582        128            [128]
    2     4846          5              [5]
    3     1709          9              [9]
    4    59239    105.104       [105, 104]

我想选择特定列表[480,9,104]中至少一个类别的所有行。

预期输出:

  album_id categories split_categories
0    66562    480.494       [480, 494]
3     1709          9              [9]
4    59239    105.104       [105, 104]

我设法使用apply

def match_categories(row):
    selected_categories =  [480, 9, 104]
    result = [int(i) for i in row['split_categories'] if i in selected_categories]
    return result

df['matched_categories'] = df.apply(match_categories, axis=1)

但是此代码在生产环境中运行,并且这种方式花费的时间太长(我对包含列表的多列运行它)

有没有办法运行类似的东西:

df[~(df['split_categories'].anyvalue.isin([480, 9, 104]))]

谢谢

5 个答案:

答案 0 :(得分:2)

您可以将每个列表转换为集合,获取交集并将其转换为bool:

L = [480, 9, 104]
mask = np.array([bool(set(map(int, x)) & set(L))  for x in df['split_categories']])

或将list column转换为DataFrame,强制转换为浮点并与isin比较:

df1 = pd.DataFrame(df['split_categories'].values.tolist(), index=df.index)
mask = df1.astype(float).isin(L).any(axis=1)

df = df[mask]
print (df)
  album_id categories split_categories
0    66562    480.494       [480, 494]
3     1709          9              [9]
4    59239    105.104       [105, 104]

答案 1 :(得分:2)

您可以展开内部列表,并检查内部列表中的any项是否包含在[480, 9, 104]中:

l = [480, 9, 104]
df[df.categories.str.split('.', expand=True).isin(map(str,l)).any(axis=1)]

   album_id  categories split_categories
0     66562     480.494        [480,494]
3      1709       9.000              [9]
4     59239     105.104        [105,104]

答案 2 :(得分:1)

使用:

print(df[~(df['split_categories'].isin([480, 9, 104])).any()])

输出:

  album_id categories split_categories
0    66562    480.494       [480, 494]
3     1709          9              [9]
4    59239    105.104       [105, 104]

答案 3 :(得分:1)

避免使用一系列列表

您可以拆分为多个数字序列,然后使用矢量化布尔运算。使用逐行操作的Python级别循环通常效率更高( )。

  const foo = () => {
     return gulp.src("...")
     .pipe(changed("..."))
     .pipe(gulp.dest(function (file) {
      // ...stuff
      return "...";
    }));
  }

答案 4 :(得分:1)

另一种方法:

my_list = [480, 9, 104]
pat = r'({})'.format('|'.join(str(i) for i in my_list))
#'(480|9|104)' <-- This is how the pat looks like
df.loc[df.split_categories.astype(str).str.extract(pat, expand=False).dropna().index]

或者:

pat = '|'.join(r"\b{}\b".format(x) for x in my_list)
df[df.split_categories.astype(str).str.contains(pat,na=False)]

    album_id    categories  split_categories
0   66562       480.494     [480, 494]
3   1709        9.000       [9]
4   59239       105.104     [105, 104]

这将与split_categoriescategories列一起使用。