Thêm ID được tìm thấy trong danh sách vào cột mới trong khung dữ liệu gấu trúc


11

Giả sử tôi có khung dữ liệu sau (cột số nguyên và cột có danh sách số nguyên) ...

      ID                   Found_IDs
0  12345        [15443, 15533, 3433]
1  15533  [2234, 16608, 12002, 7654]
2   6789      [43322, 876544, 36789]

Và cũng là một danh sách ID riêng biệt ...

bad_ids = [15533, 876544, 36789, 11111]

Cho rằng, và bỏ qua df['ID']cột và bất kỳ chỉ mục nào, tôi muốn xem liệu có bất kỳ ID nào trong bad_idsdanh sách được đề cập trong df['Found_IDs']cột không. Mã tôi có cho đến nay là:

df['bad_id'] = [c in l for c, l in zip(bad_ids, df['Found_IDs'])]

Điều này hoạt động nhưng chỉ khi bad_idsdanh sách dài hơn khung dữ liệu và đối với tập dữ liệu thực, bad_idsdanh sách sẽ ngắn hơn rất nhiều so với khung dữ liệu. Nếu tôi đặt bad_idsdanh sách chỉ có hai yếu tố ...

bad_ids = [15533, 876544]

Tôi nhận được một lỗi rất phổ biến (tôi đã đọc nhiều câu hỏi với cùng một lỗi) ...

ValueError: Length of values does not match length of index

Tôi đã thử chuyển đổi danh sách thành một chuỗi (không thay đổi lỗi). Tôi cũng đã thử thêm cột mới và đặt tất cả các giá trị Falsetrước khi thực hiện dòng hiểu (một lần nữa không có thay đổi trong lỗi).

Hai câu hỏi:

  1. Làm cách nào để mã của tôi (bên dưới) hoạt động cho danh sách ngắn hơn khung dữ liệu?
  2. Làm cách nào để tôi nhận được mã để viết ID thực tế được tìm thấy trở lại df['bad_id']cột (hữu ích hơn Đúng / Sai)?

Sản lượng dự kiến ​​cho bad_ids = [15533, 876544]:

      ID                   Found_IDs  bad_id
0  12345        [15443, 15533, 3433]    True
1  15533  [2234, 16608, 12002, 7654]   False
2   6789      [43322, 876544, 36789]    True

Đầu ra lý tưởng cho bad_ids = [15533, 876544](ID) được ghi vào một cột hoặc cột mới):

      ID                   Found_IDs  bad_id
0  12345        [15443, 15533, 3433]    15533
1  15533  [2234, 16608, 12002, 7654]   False
2   6789      [43322, 876544, 36789]    876544

Mã số:

import pandas as pd

result_list = [[12345,[15443,15533,3433]],
        [15533,[2234,16608,12002,7654]],
        [6789,[43322,876544,36789]]]

df = pd.DataFrame(result_list,columns=['ID','Found_IDs'])

# works if list has four elements
# bad_ids = [15533, 876544, 36789, 11111]

# fails if list has two elements (less elements than the dataframe)
# ValueError: Length of values does not match length of index
bad_ids = [15533, 876544]

# coverting to Series doesn't change things
# bad_ids = pd.Series(bad_ids)
# print(type(bad_ids))

# setting up a new column of false values doesn't change things
# df['bad_id'] = False

print(df)

df['bad_id'] = [c in l for c, l in zip(bad_ids, df['Found_IDs'])]

print(bad_ids)

print(df)

Câu trả lời:


7

Sử dụng np.intersect1dđể có được giao điểm của hai danh sách:

df['bad_id'] = df['Found_IDs'].apply(lambda x: np.intersect1d(x, bad_ids))

      ID                   Found_IDs    bad_id
0  12345        [15443, 15533, 3433]   [15533]
1  15533  [2234, 16608, 12002, 7654]        []
2   6789      [43322, 876544, 36789]  [876544]

Hoặc chỉ với con trăn vanilla sử dụng giao điểm của sets:

bad_ids_set = set(bad_ids)
df['Found_IDs'].apply(lambda x: list(set(x) & bad_ids_set))

3

Nếu muốn kiểm tra tất cả các giá trị của danh sách trong Found_IDscột bằng tất cả các giá trị bad_idssử dụng:

bad_ids = [15533, 876544]

df['bad_id'] = [any(c in l for c in bad_ids) for l  in df['Found_IDs']]
print (df)
      ID                   Found_IDs  bad_id
0  12345        [15443, 15533, 3433]    True
1  15533  [2234, 16608, 12002, 7654]   False
2   6789      [43322, 876544, 36789]    True

Nếu muốn tất cả khớp:

df['bad_id'] = [[c for c in bad_ids if c in l] for l  in df['Found_IDs']]
print (df)
      ID                   Found_IDs    bad_id
0  12345        [15443, 15533, 3433]   [15533]
1  15533  [2234, 16608, 12002, 7654]        []
2   6789      [43322, 876544, 36789]  [876544]

Và đối với trận đấu đầu tiên, nếu danh sách trống được đặt False, giải pháp có thể, nhưng không khuyến nghị trộn boolean và số:

df['bad_id'] = [next(iter([c for c in bad_ids if c in l]), False) for l  in df['Found_IDs']]
print (df)
      ID                   Found_IDs  bad_id
0  12345        [15443, 15533, 3433]   15533
1  15533  [2234, 16608, 12002, 7654]   False
2   6789      [43322, 876544, 36789]  876544

Giải pháp với bộ:

df['bad_id'] = df['Found_IDs'].map(set(bad_ids).intersection)
print (df)

      ID                   Found_IDs    bad_id
0  12345        [15443, 15533, 3433]   {15533}
1  15533  [2234, 16608, 12002, 7654]        {}
2   6789      [43322, 876544, 36789]  {876544}

Và cũng tương tự với việc hiểu danh sách:

df['bad_id'] = [list(set(bad_ids).intersection(l)) for l  in df['Found_IDs']]
print (df)
      ID                   Found_IDs    bad_id
0  12345        [15443, 15533, 3433]   [15533]
1  15533  [2234, 16608, 12002, 7654]        []
2   6789      [43322, 876544, 36789]  [876544]

1

Bạn có thể áp dụng và sử dụng np.any:

df['bad_id'] = df['Found_IDs'].apply(lambda x: np.any([c in x for c in bad_ids]))

Điều này trả về bool nếu tồn tại bad_id trong Found_IDs, nếu bạn muốn truy xuất bad_ids này:

df['bad_id'] = df['Found_IDs'].apply(lambda x: [*filter(lambda x: c in x, bad_ids)])

Điều này sẽ trả về một danh sách các bad_ids tại Found_ids, nếu có 0 thì nó trả về []


1

sử dụng mergeconcattrong khi nhóm theo chỉ mục của bạn để trả về tất cả các trận đấu.

bad_ids = [15533, 876544, 36789, 11111]

df2 = pd.concat(
    [
        df,
        pd.merge(
            df["Found_IDs"].explode().reset_index(),
            pd.Series(bad_ids, name="bad_ids"),
            left_on="Found_IDs",
            right_on="bad_ids",
            how="inner",
        )
        .groupby("index")
        .agg(bad_ids=("bad_ids", list)),
    ],
    axis=1,
).fillna(False)
print(df2)


      ID                   Found_IDs          bad_ids
0  12345        [15443, 15533, 3433]          [15533]
1  15533  [2234, 16608, 12002, 7654]            False
2   6789      [43322, 876544, 36789]  [876544, 36789]

0

Sử dụng tổng hợp nổ và nhóm

s = df['Found_IDs'].explode()
df['bad_ids'] = s.isin(bad_ids).groupby(s.index).any()

Dành cho bad_ids = [15533, 876544]

>>> df
      ID                   Found_IDs  bad_ids
0  12345        [15443, 15533, 3433]     True
1  15533  [2234, 16608, 12002, 7654]    False
2   6789      [43322, 876544, 36789]     True

HOẶC LÀ

Để nhận giá trị khớp

s = df['Found_IDs'].explode()
s.where(s.isin(bad_ids)).groupby(s.index).agg(lambda x: list(x.dropna()))

Dành cho bad_ids = [15533, 876544]

      ID                   Found_IDs   bad_ids
0  12345        [15443, 15533, 3433]   [15533]
1  15533  [2234, 16608, 12002, 7654]        []
2   6789      [43322, 876544, 36789]  [876544]
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.