Pandas 数据框条件替换和按列修剪
Pandas dataframe conditional substitution and columnwise trimming
Current Pandas DataFrame
fn1 = pd.DataFrame([['A', 'NaN', 'NaN', 9, 6], ['B', 'NaN', 2, 'NaN', 7], ['C', 3, 2, 'NaN', 10], ['D', 'NaN', 7, 'NaN', 'NaN'], ['E', 'NaN', 'NaN', 3, 3], ['F', 'NaN', 'NaN', 7,'NaN']], columns = ['Symbol', 'Condition1','Condition2', 'Condition3', 'Condition4'])
fn1.set_index('Symbol', inplace=True)
Condition1 Condition2 Condition3 Condition4
Symbol
A NaN NaN 9 6
B NaN 2 NaN 7
C 3 2 NaN 10
D NaN 7 NaN NaN
E NaN NaN 3 3
F NaN NaN 7 NaN
我目前正在使用看起来像上面的 link 的 Pandas DataFrame。我正在尝试逐列将不是 'NaN' 的值替换为与该行关联的 'Symbol' 然后折叠每一列(或写入新的 DataFrame),以便每一列都是一个列表每个 'Condition' 中存在的 'Symbol' 个,如所需输出所示:
Desired Output
我已经能够将每个条件下存在的 'Symbols' 放入一个列表列表中(见下文),但我想保持相同的列名并且无法将它们添加到永远-增加新的 DataFrame,因为长度是可变的,我正在循环列。
ls2 = []
for col in fn1.columns:
fn2 = fn1[fn1[col] > 0]
ls2.append(list(fn2.index))
其中 fn1 是看起来像第一张图片的 DataFrame,我已将 'Symbol' 列作为索引。
提前感谢您的帮助。
您可以将符号映射到每一列,然后取一组非空值。
df = fn1.apply(lambda x: x.map(fn1['Symbol'].to_dict()))
condition_symbols = {col:sorted(list(set(fn1_symbols[col].dropna()))) for col in fn1.columns[1:]}
这会给你一本字典:
{'Condition1': ['B', 'D'],
'Condition2': ['C', 'H'],
'Condition3': ['D', 'H', 'J'],
'Condition4': ['D', 'G', 'H', 'K']}
我知道您要的是 Dataframe,但由于每个列表的长度不同,因此将其放入 Dataframe 没有意义。如果你想要一个 Dataframe,那么你可以 运行 这个代码:
pd.DataFrame(dict([ (k,pd.Series(v)) for k,v in condition_symbols.items() ]))
这将为您提供以下输出:
Condition1 Condition2 Condition3 Condition4
0 B C D D
1 D H H G
2 NaN NaN J H
3 NaN NaN NaN K
另一种答案是切片,就像下面(评论中的解释):
import numpy as np
import pandas as pd
df = pd.DataFrame.from_dict({
"Symbol": ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k"],
"Condition1": [1, np.nan, 3, np.nan, np.nan, np.nan, 7, np.nan, np.nan, 8, 12],
"Condition2": [np.nan, 2, 2, 7, np.nan, np.nan, 5, 11, 14, np.nan, np.nan],
}
)
new_df = pd.concat(
[
df["Symbol"][df[column].notnull()].reset_index(drop=True) # get columns without null and ignore the index (as your output suggests)
for column in list(df)[1:] # Iterate over all columns except "Symbols"
],
axis=1, # Column-wise concatenation
)
# Rename columns
new_df.columns = list(df)[1:]
# You can leave NaNs or replace them with empty string, your choice
new_df.fillna("", inplace=True)
此操作的输出将是:
Condition1 Condition2
0 a b
1 c c
2 g d
3 j g
4 k h
5 i
如果您需要任何进一步的说明,请在下方post发表评论。
Current Pandas DataFrame
fn1 = pd.DataFrame([['A', 'NaN', 'NaN', 9, 6], ['B', 'NaN', 2, 'NaN', 7], ['C', 3, 2, 'NaN', 10], ['D', 'NaN', 7, 'NaN', 'NaN'], ['E', 'NaN', 'NaN', 3, 3], ['F', 'NaN', 'NaN', 7,'NaN']], columns = ['Symbol', 'Condition1','Condition2', 'Condition3', 'Condition4'])
fn1.set_index('Symbol', inplace=True)
Condition1 Condition2 Condition3 Condition4
Symbol
A NaN NaN 9 6
B NaN 2 NaN 7
C 3 2 NaN 10
D NaN 7 NaN NaN
E NaN NaN 3 3
F NaN NaN 7 NaN
我目前正在使用看起来像上面的 link 的 Pandas DataFrame。我正在尝试逐列将不是 'NaN' 的值替换为与该行关联的 'Symbol' 然后折叠每一列(或写入新的 DataFrame),以便每一列都是一个列表每个 'Condition' 中存在的 'Symbol' 个,如所需输出所示:
Desired Output
我已经能够将每个条件下存在的 'Symbols' 放入一个列表列表中(见下文),但我想保持相同的列名并且无法将它们添加到永远-增加新的 DataFrame,因为长度是可变的,我正在循环列。
ls2 = []
for col in fn1.columns:
fn2 = fn1[fn1[col] > 0]
ls2.append(list(fn2.index))
其中 fn1 是看起来像第一张图片的 DataFrame,我已将 'Symbol' 列作为索引。
提前感谢您的帮助。
您可以将符号映射到每一列,然后取一组非空值。
df = fn1.apply(lambda x: x.map(fn1['Symbol'].to_dict()))
condition_symbols = {col:sorted(list(set(fn1_symbols[col].dropna()))) for col in fn1.columns[1:]}
这会给你一本字典:
{'Condition1': ['B', 'D'],
'Condition2': ['C', 'H'],
'Condition3': ['D', 'H', 'J'],
'Condition4': ['D', 'G', 'H', 'K']}
我知道您要的是 Dataframe,但由于每个列表的长度不同,因此将其放入 Dataframe 没有意义。如果你想要一个 Dataframe,那么你可以 运行 这个代码:
pd.DataFrame(dict([ (k,pd.Series(v)) for k,v in condition_symbols.items() ]))
这将为您提供以下输出:
Condition1 Condition2 Condition3 Condition4
0 B C D D
1 D H H G
2 NaN NaN J H
3 NaN NaN NaN K
另一种答案是切片,就像下面(评论中的解释):
import numpy as np
import pandas as pd
df = pd.DataFrame.from_dict({
"Symbol": ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k"],
"Condition1": [1, np.nan, 3, np.nan, np.nan, np.nan, 7, np.nan, np.nan, 8, 12],
"Condition2": [np.nan, 2, 2, 7, np.nan, np.nan, 5, 11, 14, np.nan, np.nan],
}
)
new_df = pd.concat(
[
df["Symbol"][df[column].notnull()].reset_index(drop=True) # get columns without null and ignore the index (as your output suggests)
for column in list(df)[1:] # Iterate over all columns except "Symbols"
],
axis=1, # Column-wise concatenation
)
# Rename columns
new_df.columns = list(df)[1:]
# You can leave NaNs or replace them with empty string, your choice
new_df.fillna("", inplace=True)
此操作的输出将是:
Condition1 Condition2
0 a b
1 c c
2 g d
3 j g
4 k h
5 i
如果您需要任何进一步的说明,请在下方post发表评论。