我有一个数据框:
a b c d......
1 1
3 3 3 5
4 1 1 4 6
1 0
我想根据列#34; a"中给出的值选择列数。在这种情况下,对于第一行,它只会选择列b。 我怎样才能实现以下目标:
df.iloc[:,column b:number of columns corresponding to value in column a]
我的预期输出是:
a b c d e
1 1 0 0 1 # 'e' contains value in column b because colmn a = 1
3 3 3 5 335 # 'e' contains values of column b,c,d because colm a
4 1 1 4 1 # = 3
1 0 NAN
答案 0 :(得分:3)
为此定义一个小功能:
def select(df, r):
return df.iloc[r, 1:1 + df.iat[r, 0]]
该函数使用iat
查询该行的a
列,iloc
选择同一行中的列。
这样称呼:
select(df, 0)
b 1.0
Name: 0, dtype: float64
而且,
select(df, 1)
b 3.0
c 3.0
d 5.0
Name: 1, dtype: float64
根据您的修改,请考虑这一点 -
df
a b c d e
0 1 1 0 0 0
1 3 3 3 5 0
2 4 1 1 4 6
3 1 0 0 0 0
在这里使用where
/ mask
(与numpy广播)+ agg
-
df['e'] = df.iloc[:, 1:]\
.astype(str)\
.where(np.arange(df.shape[1] - 1) < df.a[:, None], '')\
.agg(''.join, axis=1)
df
a b c d e
0 1 1 0 0 1
1 3 3 3 5 335
2 4 1 1 4 1146
3 1 0 0 0 0
如果没有匹配,则e
中的条目将为空字符串。只需使用replace
-
df['e'] = df['e'].replace('', np.nan)
答案 1 :(得分:2)
一种numpy切片方法
a = v[:, 0]
b = v[:, 1:]
n, m = b.shape
b = b.ravel()
b = np.where(b == 0, '', b.astype(str))
r = np.arange(n) * m
f = lambda t: b[t[0]:t[1]]
df.assign(g=list(map(''.join, map(f, zip(r, r + a)))))
a b c d e g
0 1 1 0 0 0 1
1 3 3 3 5 0 335
2 4 1 1 4 6 1146
3 1 0 0 0 0
答案 2 :(得分:1)
编辑:带切片的一行解决方案。
df["f"] = df.astype(str).apply(lambda r: "".join(r[1:int(r["a"])+1]), axis=1)
# df["f"] = df["f"].astype(int) if you need `f` to be integer
df
a b c d e f
0 1 1 X X X 1
1 3 3 3 5 X 335
2 4 1 1 4 6 1146
3 1 0 X X X 0
使用数据集:
df = pd.DataFrame({'a': {0: 1, 1: 3, 2: 4, 3: 1},
'b': {0: 1, 1: 3, 2: 1, 3: 0},
'c': {0: 'X', 1: '3', 2: '1', 3: 'X'},
'd': {0: 'X', 1: '5', 2: '4', 3: 'X'},
'e': {0: 'X', 1: 'X', 2: '6', 3: 'X'}})
建议改进建议!