有效地将 pandas 数据框列名转换为行值
Efficiently transforming pandas dataframe column names into row values
我正在处理站点密钥的日志数据,然后是 key/value 对事件和时间戳。预处理将其作为无法确定列数(可能是 1-N)的 pandas 数据帧提供,其中列是键,值是时间戳。我知道这是一个不太理想的结构,但我无法更改它。什么是对数据框进行操作的有效方法,以便对于每个键,我都能够计算非空列并识别非空值?
这里是假设 raw data:
KeyCol ValCol1 ValCol2 ValCol3
A ValCol1 ValCol2 nan
B nan nan nan
C ValCol1 nan ValCol3
D nan ValCol2 nan
C nan nan ValCol3
这是 desired output:
KeyCol Len Vals
A 2 [ValCol1, ValCol2]
B 0 []
C 2 [ValCol1, ValCol3]
D 1 [ValCol2]
这是我到目前为止所做的...但它似乎效率低下。我将如何优化它?
import pandas as pd
def iterate_rows_for_nonnulls(df, grouper):
assert isinstance(df, pd.DataFrame)
assert isinstance(grouper, (list, tuple))
aggdic = {}
for row, data in df.iterrows():
key = tuple(data[grouper])
nonnulls = data[~data.index.isin(grouper)]
nonnulls = nonnulls[nonnulls.notnull()]
data[data.notnull()]
if key not in aggdic:
aggdic[key] = {}
aggdic[key]['vals'] = nonnulls
else:
aggdic[key]['vals'] = aggdic[key]['vals'].append(nonnulls)
for key, val in aggdic.iteritems():
aggdic[key]['vals'] = aggdic[key]['vals'].unique()
aggdic[key]['len'] = len(aggdic[key]['vals'])
# Testing using [key for key in aggdic.iteritems() if aggdic[key[0]]['len']>0 ]
return aggdic
def construct_df_from_nonnulls(aggdic):
assert isinstance(aggdic, dict)
return pd.DataFrame(dict(aggdic)).T
sourcedf = pd.read_table('https://gist.githubusercontent.com/roablep/a11da82de18b14bd2c3c/raw/257f2fa7634002db267e2ef599d6e0cd330c1c72/Sourcedata', sep = "\t")
aggdic = iterate_rows_for_nonnulls(sourcedf, ['KeyCol'])
resultsdf = construct_df_from_nonnulls(aggdic)
假设我对你的理解是正确的——列名与这些列中所有元素的值相同是很奇怪的——我认为你可以在 melt
ing:
>>> d2 = pd.melt(df,id_vars="KeyCol")
>>> grouped = d2.groupby("KeyCol", as_index=False)["value"]
>>> dout = grouped.agg({"Len": "nunique",
"Vals": lambda x: x.dropna().unique().tolist()})
>>> dout
KeyCol Vals Len
0 A [ValCol1, ValCol2] 2
1 B [] 0
2 C [ValCol1, ValCol3] 2
3 D [ValCol2] 1
强烈建议阅读有关 split-apply-combine
模式的文档部分。
也就是说,请注意,将非标量对象(例如序列中的列表或 DataFrames)作为元素放置是令人头疼的问题——它们实际上不受支持。它有时可以用作中间步骤的临时措施,但在完成之后你不能对那个系列做太多事情。
我正在处理站点密钥的日志数据,然后是 key/value 对事件和时间戳。预处理将其作为无法确定列数(可能是 1-N)的 pandas 数据帧提供,其中列是键,值是时间戳。我知道这是一个不太理想的结构,但我无法更改它。什么是对数据框进行操作的有效方法,以便对于每个键,我都能够计算非空列并识别非空值?
这里是假设 raw data:
KeyCol ValCol1 ValCol2 ValCol3
A ValCol1 ValCol2 nan
B nan nan nan
C ValCol1 nan ValCol3
D nan ValCol2 nan
C nan nan ValCol3
这是 desired output:
KeyCol Len Vals
A 2 [ValCol1, ValCol2]
B 0 []
C 2 [ValCol1, ValCol3]
D 1 [ValCol2]
这是我到目前为止所做的...但它似乎效率低下。我将如何优化它?
import pandas as pd
def iterate_rows_for_nonnulls(df, grouper):
assert isinstance(df, pd.DataFrame)
assert isinstance(grouper, (list, tuple))
aggdic = {}
for row, data in df.iterrows():
key = tuple(data[grouper])
nonnulls = data[~data.index.isin(grouper)]
nonnulls = nonnulls[nonnulls.notnull()]
data[data.notnull()]
if key not in aggdic:
aggdic[key] = {}
aggdic[key]['vals'] = nonnulls
else:
aggdic[key]['vals'] = aggdic[key]['vals'].append(nonnulls)
for key, val in aggdic.iteritems():
aggdic[key]['vals'] = aggdic[key]['vals'].unique()
aggdic[key]['len'] = len(aggdic[key]['vals'])
# Testing using [key for key in aggdic.iteritems() if aggdic[key[0]]['len']>0 ]
return aggdic
def construct_df_from_nonnulls(aggdic):
assert isinstance(aggdic, dict)
return pd.DataFrame(dict(aggdic)).T
sourcedf = pd.read_table('https://gist.githubusercontent.com/roablep/a11da82de18b14bd2c3c/raw/257f2fa7634002db267e2ef599d6e0cd330c1c72/Sourcedata', sep = "\t")
aggdic = iterate_rows_for_nonnulls(sourcedf, ['KeyCol'])
resultsdf = construct_df_from_nonnulls(aggdic)
假设我对你的理解是正确的——列名与这些列中所有元素的值相同是很奇怪的——我认为你可以在 melt
ing:
>>> d2 = pd.melt(df,id_vars="KeyCol")
>>> grouped = d2.groupby("KeyCol", as_index=False)["value"]
>>> dout = grouped.agg({"Len": "nunique",
"Vals": lambda x: x.dropna().unique().tolist()})
>>> dout
KeyCol Vals Len
0 A [ValCol1, ValCol2] 2
1 B [] 0
2 C [ValCol1, ValCol3] 2
3 D [ValCol2] 1
强烈建议阅读有关 split-apply-combine
模式的文档部分。
也就是说,请注意,将非标量对象(例如序列中的列表或 DataFrames)作为元素放置是令人头疼的问题——它们实际上不受支持。它有时可以用作中间步骤的临时措施,但在完成之后你不能对那个系列做太多事情。