簡體   English   中英

如何創建從列中獲取的唯一值的熊貓數據框,沒有重復項

[英]How to create a pandas dataframe of unique values fetched from column with no duplicates

我有一個熊貓數據框df

import pandas as pd

df = pd.DataFrame({"ID": [2,3,4,5,6,7,8,9,10],
              "type" :["A", "B", "B", "A", "A", "B", "A", "A", "A"],
              "F_ID" :["0", "[7 8 9]", "[10]", "0", "[2]", "0", "0", "0", "0"]})

看起來像:

      F_ID  ID type
0        0   2    A
1  [7 8 9]   3    B
2     [10]   4    B
3        0   5    A
4      [2]   6    A
5        0   7    B
6        0   8    A
7        0   9    A
8        0  10    A

在此,F_ID是一列,它基於某些計算來告訴哪些記錄與該關節記錄匹配。 它給出了匹配的ID值。 因此,ID 3與ID 7和8匹配。

我想要所有B類型ID及其相關記錄的列表。 如果在單獨的列的F_ID列中提到匹配ID,則該列的編號可能會根據值而有所不同,如下所示:

ID  type F_ID_1  F_ID_2 
3    B    8      9
4    B    10      
7    B

我不需要提到的那些B類型的F_ID的值。例如,ID 3具有7、8、9作為匹配ID,但是由於第7個ID是B類型,因此不應將其稱為F_ID,並且僅必須列出8和9。

如何使用python中的pandas做到這一點?

如果我了解您的意圖,那么F_ID是列表的字符串表示形式?

如果是這樣,請將其轉換為實際列表:

import numpy as np
import pandas as pd

df = pd.DataFrame({"ID": [2,3,4,5,6,7,8,9,10],
      "type" :["A", "B", "B", "A", "A", "B", "A", "A", "A"],
      "F_ID" :["0", "[7 8 9]", "[10]", "0", "[2]", "0", "0", "0", "0"]})

# convert the string representations of list structures to actual lists
F_ID_as_series_of_lists = df["F_ID"].str.replace("[","").str.replace("]","").str.split(" ")

#type(F_ID_as_series_of_lists) is pd.Series, make it a list for pd.DataFrame.from_records
F_ID_as_records = list(F_ID_as_series_of_lists)

f_id_df = pd.DataFrame.from_records(list(F_ID_as_records)).fillna(np.nan)
f_id_df

F_ID作為列表

現在,讓我們將拆分后的F_ID加入到原始DataFrame中

combined_df = df.merge(f_id_df, left_index = True, right_index = True, how = "inner")
combined_df = combined_df.drop("F_ID", axis = 1).sort_values(["type", "ID"])
combined_df

已加入F_Id

但是,我們需要省略在同一typeID出現的F_ID ,即由於7type == "B"ID ,因此我們想在ID == 3type == "B"將其排除,即使盡管它在F_ID的列表中。

為此,我們創建ID / typeF_ID映射。

mapping_df = pd.DataFrame(combined_df.set_index(["ID", "type"]).stack()).reset_index().drop("level_2", axis = 1)
mapping_df.columns = ["ID", "type", "F_ID"]
mapping_df

映射數據框

現在進行過濾,我們可能可以做一些令人印象深刻的聯接,但是如果我們不得不回到這個例子,則更容易閱讀該示例的查詢:

def is_fid_of_same_type(row, df):
    query = "ID == {row_fid} & type == '{row_type}'".format(
        row_fid = row["F_ID"],
        row_type = row["type"]
    )

    matches_df = df.query(query)

    row["fid_in_type_id"] = len(matches_df) > 0
    return row

現在,將此功能應用於每一行,並將確實顯示為F_ID的行作為同一typeID F_ID

df = mapping_df.apply(lambda row: is_fid_of_same_type(row, mapping_df), axis = 1)
df = df[df["fid_in_type_id"] == False].drop("fid_in_type_id", axis = 1)
df

排除了我們要排除的行

然后, F_ID作為列表而不是單獨的行,請使用DataFrame.groupby()然后apply(list)

group_columns = ['type', 'ID']
df = df.groupby(group_columns)['F_ID'].apply(list).reset_index()
df = df.sort_values(group_columns).set_index(group_columns)
df

結果是:

最后結果

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM