Python 在Pandas中指定单元格值的最快方法
我有一个元组列表:Python 在Pandas中指定单元格值的最快方法,python,pandas,numpy,Python,Pandas,Numpy,我有一个元组列表: d = [("a", "x"), ("b", "y"), ("a", "y")] 以及数据帧: y x b 0.0 0.0 a 0.0 0.0 如果行和列标签对应于d中的元组,则我想将任何0s替换为1s,这样新的数据帧是: y x b 1.0 0.0 a 1.0 1.0 我目前正在使用: for i, j in d: df.loc[i, j] = 1.0 在我看来,这似乎是最“pythonic”的方法,但对于形状
d = [("a", "x"), ("b", "y"), ("a", "y")]
以及数据帧
:
y x
b 0.0 0.0
a 0.0 0.0
如果行和列标签对应于d
中的元组,则我想将任何0s
替换为1s
,这样新的数据帧是:
y x
b 1.0 0.0
a 1.0 1.0
我目前正在使用:
for i, j in d:
df.loc[i, j] = 1.0
在我看来,这似乎是最“pythonic”的方法,但对于形状为20000*20000的DataFrame
和长度为10000的列表,这一过程实际上需要永远的时间。必须有更好的方法来实现这一点。有什么想法吗
感谢与数据帧一起使用构造函数:
df = pd.get_dummies(pd.DataFrame(d).set_index(0)[1]).rename_axis(None).max(level=0)
或者将zip
与系列一起使用:
lst = list(zip(*d))
df = pd.get_dummies(pd.Series(lst[1], index = lst[0])).max(level=0)
方法#1:dd
这里有一个基于NumPy的方法-
def assign_val(df, d, newval=1):
# Get d-rows,cols as arrays for efficient usage latet on
di,dc = np.array([j[0] for j in d]), np.array([j[1] for j in d])
# Get col and index data
i,c = df.index.values.astype(di.dtype),df.columns.values.astype(dc.dtype)
# Locate row indexes from d back to df
sidx_i = i.argsort()
I = sidx_i[np.searchsorted(i,di,sorter=sidx_i)]
# Locate column indexes from d back to df
sidx_c = c.argsort()
C = sidx_c[np.searchsorted(c,dc,sorter=sidx_c)]
# Assign into array data with new values
df.values[I,C] = newval
# Use df.to_numpy(copy=False)[I,C] = newval on newer pandas versions
return df
样本运行-
In [21]: df = pd.DataFrame(np.zeros((2,2)), columns=['y','x'], index=['b','a'])
In [22]: d = [("a", "x"), ("b", "y"), ('a','y')]
In [23]: assign_val(df, d, newval=1)
Out[23]:
y x
b 1.0 0.0
a 1.0 1.0
方法#2:通用方法
如果'd'中有任何不正确的条目,我们需要过滤掉这些条目。因此,对于一般情况,修改后的-
def ssidx(i,di):
sidx_i = i.argsort()
idx_i = np.searchsorted(i,di,sorter=sidx_i)
invalid_mask = idx_i==len(sidx_i)
idx_i[invalid_mask] = 0
I = sidx_i[idx_i]
invalid_mask |= i[I]!=di
return I,invalid_mask
# Get d-rows,cols as arrays for efficient usage latet on
di,dc = np.array([j[0] for j in d]), np.array([j[1] for j in d])
# Get col and index data
i,c = df.index.values.astype(di.dtype),df.columns.values.astype(dc.dtype)
# Locate row indexes from d back to df
I,badmask_I = ssidx(i,di)
# Locate column indexes from d back to df
C,badmask_C = ssidx(c,dc)
badmask = badmask_I | badmask_C
goodmask = ~badmask
df.values[I[goodmask],C[goodmask]] = newval
如果列表中有重复的元素,则此操作不起作用,因为生成的数据帧会重复这些行/列。我更新了我的示例。熊猫不是进行此类操作的最佳工具。根据您的描述,我认为您需要查看稀疏矩阵(scipy.Sparse)。我得到的错误索引I超出轴0的范围,大小为I
,在I=sidx\u I[np.searchsorted(I,di,sorter=sidx\u I)]
行。这可能意味着什么?@harrystat是否保证d
中的所有字符串都来自df的索引和列?嗯,不,不一定。@harrystat那么,该如何处理这种情况呢?分配时是否应跳过d中的元组?@HarryStudio添加了一个通用解决方案。
def ssidx(i,di):
sidx_i = i.argsort()
idx_i = np.searchsorted(i,di,sorter=sidx_i)
invalid_mask = idx_i==len(sidx_i)
idx_i[invalid_mask] = 0
I = sidx_i[idx_i]
invalid_mask |= i[I]!=di
return I,invalid_mask
# Get d-rows,cols as arrays for efficient usage latet on
di,dc = np.array([j[0] for j in d]), np.array([j[1] for j in d])
# Get col and index data
i,c = df.index.values.astype(di.dtype),df.columns.values.astype(dc.dtype)
# Locate row indexes from d back to df
I,badmask_I = ssidx(i,di)
# Locate column indexes from d back to df
C,badmask_C = ssidx(c,dc)
badmask = badmask_I | badmask_C
goodmask = ~badmask
df.values[I[goodmask],C[goodmask]] = newval