Listede bulunan kimliği panda veri çerçevesindeki yeni sütuna ekle


11

Diyelim ki aşağıdaki veri çerçevesi (tamsayılar sütunu ve tamsayıların listesini içeren bir sütun) ...

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

Ayrıca ayrı bir kimlik listesi ...

bad_ids = [15533, 876544, 36789, 11111]

Bu göz önüne alındığında ve df['ID']sütun ve herhangi bir dizini göz ardı ederek , bad_idslistedeki kimliklerden herhangi birinin df['Found_IDs']sütunda belirtilip belirtilmediğini görmek istiyorum . Şimdiye kadar var kod:

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

Bu işe yarar, ancak bad_idsliste veri çerçevesinden daha uzunsa ve gerçek veri kümesi için bad_idsliste veri çerçevesinden çok daha kısa olacaktır. bad_idsListeyi yalnızca iki öğeye ayarlarsam ...

bad_ids = [15533, 876544]

Çok popüler bir hata alıyorum (aynı hatayla birçok soru okudum) ...

ValueError: Length of values does not match length of index

Liste bir dizi (hata hiçbir değişiklik) dönüştürme denedim. Ben de yeni sütun ekleme ve Falseanlama hattı (yine hata hiçbir değişiklik) yapmadan önce tüm değerleri ayarlama denedim .

İki soru:

  1. Veri çerçevesinden daha kısa bir liste için kodumu (aşağıda) nasıl çalıştırabilirim?
  2. Kolona geri bulunan gerçek kimliği yazmak için kodu nasıl alabilirim df['bad_id'](Doğru / Yanlış'dan daha yararlı)?

İçin beklenen çıktı 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

bad_ids = [15533, 876544](Kimlik (ler) için ideal çıktı yeni bir sütuna veya sütunlara yazılır):

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

Kod:

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)

Yanıtlar:


7

np.intersect1dİki listenin kesişimini elde etmek için kullanma :

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]

Veya sadece kesişen vanilya python ile sets:

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

3

İsterseniz Found_IDssütundaki listelerin tüm değerlerini tüm kullanım değerleriyle test edin bad_ids:

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

Tüm eşleşme istiyorsanız:

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]

Ve ilk eşleşme için, boş liste ayarlanırsa False, olası çözüm, ancak boolean ve sayıların karıştırılması önerilmez:

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

Setlerle çözüm:

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}

Ve liste kavrayışıyla da benzer:

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

Np.any'yi uygulayabilir ve kullanabilirsiniz:

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

Bu bad_ids'i almak istiyorsanız Found_ID'lerde bir bad_id varsa, bool döndürür:

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

Bu, found_ids içindeki bad_ids listesini döndürür, 0 varsa [] döndürür


1

kullanarak mergeve concattüm eşleşmeleri döndürmek için dizininize göre gruplandırın.

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

Patlama ve gruplandırma toplamlarını kullanma

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

İçin 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

VEYA

Eşleşen değerleri almak için

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

İçin 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]
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.