![](/img/trans.png)
[英]Condensing Multiple DataFrame Columns into a Single Indicator Column in Pandas
[英]Condensing columns in a Pandas Dataframe
我正在通過 VerisPy 處理來自 Veris 項目的數據,但在將其重新格式化以用於其他應用程序時遇到了一些麻煩。
VerisPy 輸出一個數據幀,其中包含來自提交給 Veris 的 JSON 文件的解析事件信息。 數據框中的每一行都對應一個事件,詳細說明它是如何/何時發生的。 問題是它最終有數千個帶有布爾標志的列。
所以每個事件行可能有如下列:
事件編號 | 惡意軟件 | 動作黑客 | 誤用 | 演員.外部.競爭對手 | 演員.外部犯罪 | 演員.內部.員工 | 演員.內部.客戶 | 目標 |
---|---|---|---|---|---|---|---|---|
1 | 真的 | 錯誤的 | 錯誤的 | 錯誤的 | 錯誤的 | 真的 | 錯誤的 | 微軟 |
2 | 錯誤的 | 真的 | 錯誤的 | 真的 | 錯誤的 | 錯誤的 | 錯誤的 | 美國銀行 |
我想折疊/組合這些並將列值用作實際數據。 在上面的例子中,我們可能會這樣:
事件編號 | 行動 | 演員 | 目標 |
---|---|---|---|
1 | 惡意軟件 | 內部 - 員工 | 微軟 |
2 | 黑客攻擊 | 外部 - 競爭對手 | 美國銀行 |
我是 Pandas 的新手,但從文檔中嘗試了相當多的東西,結果喜憂參半。 Melt 看起來很有希望,但我不確定如何將列名放入實際的行級數據中。 有人有指點嗎?
單程:
['event_id', 'target']
為index
。split
和expand columns
以創建hierarchical columns
(我們將在點積中使用它)。hierarchical columns
extract
level 1
值並使用dataframe
進行dot product
。string manipulations
rename
columns
(我添加了 2 種重命名列的方法)以獲得所需的output
。df1 = df.set_index(['event_id', 'target'])
df1.columns = df1.columns.str.split('.', expand=True, n=1)
df = (
df1.dot(df1.columns.get_level_values(1) + ',')
.str.strip(',')
.str.split(',', expand=True)
.rename(columns={0: 'Action', 1: 'Actor'})
.reset_index()
)
event_id target Action Actor
0 1 Microsoft malware internal.employee
1 2 Bank of America hacking external.competitor
您還可以使用level=0
列值,而不是通過rename
renaming columns
來rename
renaming columns
-
df1 = df.set_index(['event_id', 'target'])
df1.columns = df1.columns.str.split('.', expand=True, n=1)
df = (
df1.dot(df1.columns.get_level_values(1) + ',')
.str.strip(',')
.str.split(',',expand=True)
)
df.columns = dict.fromkeys(df1.columns.get_level_values(0)).keys()
df = df.reset_index()
mul
:df1 = df.set_index(['event_id', 'target'])
df1.columns = df1.columns.str.split('.', expand=True, n=1)
df = (
df1.mul(df1.columns.get_level_values(1))
.replace('', np.NAN)
.droplevel(1, axis =1)
.stack()
.unstack()
)
如果你為演員和代理1個目標,您可以使用多個值pivot_table
,而不是stack
/ unstack
:
df1 = df.set_index(['event_id', 'target'])
df1.columns = df1.columns.str.split('.', expand=True, n=1)
(
df1.mul(df1.columns.get_level_values(1))
.replace('', np.NAN)
.droplevel(1, axis =1)
.stack()
.reset_index()
.pivot_table(index = ['event_id', 'target'], columns = 'level_2' , values = 0, aggfunc = ', '.join)
)
您可以將代碼從寬翻轉為長,僅過濾True
所在的行,進行一些修改以獲得輸出。
# flip from wide to long
(pd.wide_to_long(df,
stubnames=['action','actor'],
i=['event_id','target'],
j='subs',
sep='.',
suffix='.+')
.loc[lambda df: df.any(1)] # keeps only rows that have `True`
# if any row has `True`,
# replace it with values from `subs` index
.where(lambda df: df.isna(),
lambda df: df.index.get_level_values('subs'))
.fillna('')
.droplevel('subs') # served its purpose, let it go
# use the groupby with the agg to reduce to single rows
.groupby(['event_id', 'target'])
.agg("".join)
.reset_index()
)
:
event_id target action actor
0 1 Microsoft malware internal.employee
1 2 Bank of America hacking external.competitor
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.